Làm cách nào để lệnh 'cp' không phát sinh lỗi khi tệp nguồn không tồn tại?


59

Tôi đang sử dụng Mac OS X. Tôi đang cố gắng sao chép một số tệp bằng lệnh cp cho tập lệnh xây dựng như thế này.

cp ./src/*/*.h ./aaa

Nhưng lệnh này sẽ báo lỗi nếu không có tệp .h trong thư mục ./src. Làm thế nào để thực hiện lệnh không bắn lỗi? (thất bại thầm lặng) Lỗi khiến kết quả xây dựng thất bại, nhưng tôi chỉ muốn sao chép khi chỉ có một số tệp tiêu đề.

Câu trả lời:


69

Nếu bạn đang nói về thông báo lỗi, bạn có thể ngăn chặn điều đó bằng cách gửi nó đến thùng bit:

cp ./src/*/*.h ./aaa 2>/dev/null

Nếu bạn muốn chặn mã thoát và thông báo lỗi:

cp ./src/*/*.h ./aaa 2>/dev/null || :

8
Sẽ thật tốt khi giải thích những gì :có nghĩa trong bối cảnh này.
Piotr Dobrogost

23
@PiotrDobrogost: Trong Bash và một số shell khác, dấu hai chấm là một tiện ích null (no-op). Nó được chỉ định bởi POSIX . Vì nó luôn trả về giá trị true, nên nó được sử dụng ở đây để chặn mã thoát của lỗi cp(nên được mong muốn). Vỏ dựng sẵn truecó thể được sử dụng thay thế và sẽ dễ đọc hơn.
Dennis Williamson


1
Điều này cũng sẽ bỏ qua các lỗi khác (thư mục nguồn / đích không tồn tại, tệp nguồn tồn tại nhưng không thể đọc được, toàn bộ đĩa, hệ thống tệp chỉ đọc, lỗi IO, cpkhông có trong một PATHcách nào đó ...)
Vladimir Panteleev

lỗi cú pháp gần mã thông báo bất ngờ `|| '
thang

13

Bạn đang tìm kiếm một cái gì đó dọc theo dòng

if [ -e file ]
 then cp file /somewhere
fi

(Thật không may, -ftùy chọn không phải là droid bạn đang tìm kiếm.)

Nếu bạn muốn kết hợp một quả địa cầu, điều đó sẽ không hoạt động; sử dụng findthay thế, ví dụ:

find ./src -name \*.h -exec cp {} ./destination \;

Lưu ý rằng có một vấn đề TOCTOU tiềm năng với cách tiếp cận như vậy (ví dụ: nếu bạn sử dụng set -evà tệp biến mất giữa [và các cplệnh, tập lệnh của bạn sẽ bị sập).
Vladimir Panteleev

9

Câu hỏi cũ, nhưng vẫn có thể có liên quan cho những người khác.
Nếu bạn không cần sử dụng cp, bạn có thể thử với rsync.
Để sao chép tất cả các tệp từ một nguồn vào thư mục đích, hãy chạy:

rsync -avzh --ignore-errors /path/to/source /path/to/destination

Rsync đi kèm với hầu hết các hệ thống giống Unix như Linux, Mac OS X hoặc FreeBSD.


4
Bạn có thể sử dụng rsync thay vì cp, thêm tham số --ignore-missing-args: rsync -av --ignore-missing-args ./src/*/*.h ./aaaĐiều này có lợi thế hơn --ignore-errorslà các lỗi duy nhất bị bỏ qua là những lỗi liên quan đến các tệp nguồn không tồn tại. Với --ignore-errorsmỗi lỗi được bỏ qua, có thể nguy hiểm. Ngoài ra, hãy tính đến rằng tham số này khá gần đây, vì vậy nó có thể không có trong các phiên bản cũ của rsync.
jesjimher

6

Đường ống kết quả đến đúng đảm bảo rằng lệnh sẽ luôn thành công. Tôi đã thử điều này trên Linux nhưng không phải trên bất kỳ hệ điều hành Mac nào:

cp ./src/*/*.h ./aaa | true

5
Các đường ống đơn giản |luôn luôn chạy trong khi ||chỉ được thực hiện trong trường hợp có lỗi. Và truethường là một nhị phân trong khi dấu hai chấm :là một nội trang và không tiêu thụ một PID.
ott--

Tập lệnh bash trên MacOS - Yosemite chứa lệnh "cp ./src/*/*.h ./aaa" không lỗi nếu các tệp .h không tồn tại.
Vivek

2

Bạn có thể buộc trạng thái lỗi chính xác. Với chức năng:

$ cpalways () { cp $1 $2 2>/dev/null ; return 0 ; }

Đưa ra những điều sau đây:

$ ls foo bar baz
ls: baz: No such file or directory
bar foo

Bản sao thông thường sẽ trả về một lỗi. Nó sẽ trả về trạng thái thoát là 1.

$ cp baz bar ; echo $?
cp: baz: No such file or directory
1

Nếu chúng ta sử dụng hàm cpalways () ở trên, mọi lỗi sẽ bị ẩn:

$ cpalways baz bar ; echo $?
0
$ cpalways foo bar ; echo $?
0
$ cpalways baz bar ; echo $?
0
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.