Apakah ada cara untuk secara logis menggabungkan dua perintah shell yang dipanggil dengan find - exec ?
Sebagai contoh untuk mencetak semua file .csv yang berisi string foo bersama dengan kejadiannya, saya ingin melakukan:
find . -iname \*.csv -exec grep foo {} && echo {} \;
tapi bash mengeluh dengan "argumen yang hilang ke '-exec'"
-exec
secara berurutan atau menggunakan satu-exec sh -c 'grep foo "$0" && printf %s\\n "$0"' {} \;
.sh
(dalam hal ini{}
) akan$1
dan$0
akan menjadi sesuatu sepertish
. Tetapi pada kenyataannya, Anda benar, argumen pertama muncul sebagai$0
. Memiliki argumen pertama menjadi nama perintah pemanggilan hanyalah sebuah konvensi, yang tidak secara otomatis ditegakkan dalam kasus ini.Jawaban:
-exec
adalah predikat yang menjalankan perintah (bukan shell) dan mengevaluasi true atau false berdasarkan hasil dari perintah (status keluar nol atau tidak nol).Begitu:
akan mencetak path file jika
grep
menemukan foo dalam file. Alih-alih-print
Anda dapat menggunakan-exec
predikat lain atau predikat lainLihat juga
!
dan-o
temukan operator untuk negasi dan atau .Atau, Anda dapat memulai shell sebagai:
Atau untuk menghindari keharusan memulai shell untuk setiap file:
sumber
Masalah yang Anda hadapi adalah shell pertama-tama mem-parsing baris perintah, dan melihat dua perintah sederhana yang dipisahkan oleh
&&
operator:,find . -iname \*.csv -exec grep foo {}
danecho {} \;
. Mengutip&&
(find . -iname \*.csv -exec grep foo {} '&&' echo {} \;
) bypasses itu, tapi sekarang perintah dieksekusi olehfind
adalah sesuatu sepertigrep
dengan argumenfoo
,wibble.csv
,&&
,echo
danwibble.csv
. Anda perlu menginstruksikanfind
menjalankan shell yang akan menafsirkan&&
operator:Perhatikan bahwa argumen pertama setelahnya
sh -c SOMECOMMAND
adalah$0
, bukan$1
.Anda dapat menghemat waktu startup dari proses shell untuk setiap file dengan mengelompokkan doa perintah dengan
-exec … +
. Untuk memudahkan pemrosesan, berikan beberapa nilai dummy$0
sehingga"$@"
menyebutkan nama file.Jika perintah shell hanya dipisahkan oleh dua program
&&
,find
dapat melakukan pekerjaan itu sendiri: tulis dua-exec
tindakan berurutan , dan yang kedua hanya akan dieksekusi jika yang pertama keluar dengan status 0.(Saya berasumsi itu
grep
danecho
hanya untuk tujuan ilustrasi, karena-exec echo
dapat digantikan oleh-print
dan output yang dihasilkan tidak terlalu berguna.)sumber
./some-file: grep: command not found
pesan kesalahan yang membingungkan .-exec find sh -c '... "$1"' sh {} \;
tidak akan memiliki masalah. Ada kesalahan ketik (terkait) di perintah find kedua Anda.Dalam kasus khusus ini saya akan lakukan:
find . -iname \*.csv -exec grep -l foo \{\} \;
Atau jika Anda memiliki ACK :
ack -al -G '.*\.csv' foo
Untuk menjawab pertanyaan Anda yang sebenarnya, sesuatu seperti ini dapat bekerja:
find . -iname \*.csv -exec sh -c "grep foo {} && echo {}" \;
sumber