Ini adalah batasan find
. Standar POSIX menentukan bahwa status pengembalian find
adalah 0 kecuali terjadi kesalahan saat melintasi direktori; status pengembalian dari perintah yang dieksekusi tidak masuk ke dalamnya.
Anda dapat membuat perintah menulis statusnya ke file atau ke deskriptor:
find_status_file=$(mktemp findstatus)
: >"$find_status_file"
find … -exec sh -c 'trap "echo \$?" EXIT; invalid_command "$0"' {} \;
if [ -s "$find_status_file" ]; then
echo 1>&2 "An error occurred"
fi
rm -f "$find_status_file"
Metode lain, seperti yang Anda temukan , adalah menggunakan xargs. The xargs
perintah selalu memproses semua file, tapi mengembalikan status 1 jika salah satu perintah pengembalian status nol.
find … -print0 | xargs -0 -n1 invalid_command
Namun metode lain adalah menghindari find
dan menggunakan globbing rekursif dalam shell sebagai gantinya: **/
berarti kedalaman subdirektori. Ini membutuhkan versi 4 atau lebih dari bash; macOS macet di versi 3.x sehingga Anda harus menginstalnya dari koleksi port. Gunakan set -e
untuk menghentikan skrip pada perintah pertama mengembalikan status bukan nol.
shopt -s globstar
set -e
for x in **/*.xml; do invalid_command "$x"; done
Berhati-hatilah bahwa dalam bash 4.0 hingga 4.2, ini berfungsi tetapi melintasi tautan simbolik ke direktori, yang biasanya tidak diinginkan.
Jika Anda menggunakan zsh sebagai ganti bash, globbing rekursif bekerja di luar kotak tanpa gotcha. Zsh tersedia secara default di OSX / macOS. Di zsh, Anda bisa menulis
set -e
for x in **/*.xml; do invalid_command "$x"; done
xargs
Pendekatan bekerja pada umumnya tapi entah bagaimana istirahat padabash -c
perintah. Sebagai contoh:find . -name '*.xml' -print0 | xargs -0 -n 1 -I '{}' bash -c "foo {}"
. Ini dieksekusi beberapa kali sedangkanfind . -name '2*.xml' -print0 | xargs -0 -n 1 -I '{}' foo {}
dieksekusi sekali dan gagal. Ada yang tahu kenapa?{}
di dalambash -c
. Ini mengambil nama file dan menyisipkannya langsung di dalam perintah shell. Jika nama file berisi karakter yang memiliki arti khusus di shell seperti spasi, shell mengartikan karakter khusus ini seperti itu. Jika Anda membutuhkan shell, sampaikan{}
sebagai argumen yang terpisah, misalnyabash -c 'foo "$0"' {}
(perhatikan juga tanda kutip ganda di sekitar$0
).find . -name '*' -print0 | xargs -0 -n 1 -I '{}' bash -c 'foo "$0"' {}
find . -print0 | xargs -0 -n1 invalid_command
). Ini berhenti pada kesalahan pertama benar:find . -name '*' -print0 | xargs -0 -n 1 -I '{}' foo {}
. Besar! Tetapi pendekatan yang sama tidak bekerja denganbash -c
(di atas). Satu-satunya perbedaan antara keduanya adalahbash -c
.Saya bisa menggunakan ini sebagai gantinya:
sumber
xargs
adalah salah satu pilihan. Namun, ini sebenarnya mudah untuk dilakukan denganfind
menggunakan+
alih-alih\;
Dari dokumentasi POSIX :
sumber