Bagaimana cara membiarkan perintah 'cp' jangan memunculkan kesalahan ketika file sumber tidak ada?

59

Saya menggunakan Mac OS X. Saya mencoba menyalin beberapa file dengan perintah cp untuk skrip build seperti ini.

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

Tetapi perintah ini memunculkan kesalahan jika tidak ada file .h di direktori ./src. Bagaimana cara membuat perintah jangan memecat kesalahan? (silent silent) Kesalahan membuat hasil build gagal, tapi saya hanya ingin menyalin ketika hanya ada beberapa file header.

Eonil
sumber

Jawaban:

69

Jika Anda berbicara tentang pesan kesalahan, Anda dapat menekannya dengan mengirimkannya ke keranjang bit:

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

Jika Anda ingin menekan kode keluar dan pesan kesalahan:

cp ./src/*/*.h ./aaa 2>/dev/null || :
Dennis Williamson
sumber
8
Alangkah baiknya menjelaskan apa :artinya dalam konteks ini.
Piotr Dobrogost
23
@PiotrDobrogost: Di Bash dan beberapa cangkang lainnya, usus besar adalah utilitas nol (tanpa op). Ini ditentukan oleh POSIX . Karena selalu mengembalikan true, ini digunakan di sini untuk menekan kode keluar dari yang gagal cp(harus yang diinginkan). Shell builtin truebisa digunakan sebagai gantinya dan akan lebih mudah dibaca.
Dennis Williamson
Lebih lanjut tentang :- Apa Tujuan dari `: '(titik dua) GNU Bash Builtin?
Piotr Dobrogost
1
Ini juga akan mengabaikan kesalahan lain (direktori sumber / tujuan tidak ada, file sumber ada tetapi tidak dapat dibaca, disk penuh, sistem file read-only, IO error, cptidak berada dalam PATHentah bagaimana ...)
Vladimir Panteleev
kesalahan sintaks dekat token tak terduga `|| '
thang
13

Anda sedang mencari sesuatu di sepanjang baris

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

(Sayangnya, -fopsinya bukan droid yang Anda cari.)

Jika Anda ingin mencocokkan bola dunia, itu tidak akan berhasil; gunakan findsebagai gantinya, misalnya:

find ./src -name \*.h -exec cp {} ./destination \;
Brad Ackerman
sumber
Perhatikan bahwa ada potensi masalah TOCTOU dengan pendekatan seperti itu (misalnya jika Anda menggunakan set -e, dan file menghilang antara [dan cppermintaan, skrip Anda akan macet).
Vladimir Panteleev
9

Pertanyaan lama, tetapi mungkin masih relevan untuk orang lain.
Jika Anda tidak perlu menggunakan cp, Anda bisa mencoba dengan rsync.
Untuk menyalin semua file dari sumber ke direktori tujuan, jalankan:

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

Rsync hadir dengan sebagian besar sistem mirip Unix seperti Linux, Mac OS X atau FreeBSD.

mre
sumber
4
Anda bisa menggunakan rsync daripada cp, menambahkan parameter --ignore-missing-args: rsync -av --ignore-missing-args ./src/*/*.h ./aaaIni memiliki keunggulan dibandingkan --ignore-errorssatu-satunya kesalahan yang diabaikan adalah yang terkait dengan file sumber yang tidak ada. Dengan --ignore-errorssetiap kesalahan diabaikan, yang mungkin berbahaya. Juga, perhatikan bahwa parameter ini cukup baru, jadi mungkin tidak ada di rsync versi lama.
jesjimher
6

Memipipkan hasilnya ke true memastikan bahwa perintah akan selalu berhasil. Saya sudah mencoba ini di Linux tetapi tidak di Mac OS:

cp ./src/*/*.h ./aaa | true
Vivek
sumber
5
Pipa sederhana |selalu dijalankan sementara ||hanya dilakukan jika terjadi kesalahan. Dan truebiasanya biner sedangkan usus besar :adalah builtin dan tidak mengkonsumsi PID.
ott--
Skrip bash di MacOS - Yosemite yang berisi perintah "cp ./src/*/*.h ./aaa" tidak akan salah jika file .h tidak ada.
Vivek
2

Anda bisa memaksakan status kesalahan yang benar. Dengan fungsi:

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

Diberikan sebagai berikut:

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

Salinan rutin akan menghasilkan kesalahan. Ini akan mengembalikan status keluar 1.

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

Jika kami menggunakan fungsi cpalways () di atas, kesalahan apa pun akan disembunyikan:

$ cpalways baz bar ; echo $?
0
$ cpalways foo bar ; echo $?
0
$ cpalways baz bar ; echo $?
0
Stefan Lasiewski
sumber