Bagaimana cara ini menemukan perintah menggunakan "find ... -exec sh -c '...' sh {} +" berfungsi?


8

@StephaneChazelas memposting solusi berikut untuk T&J ini: Mengalami masalah menggunakan “find -exec {} +” .

$ find . -iname "*.extension" -exec sh -c '
  exec <command> "$@" <additional parameters>' sh {} +

Apa sebenarnya yang terjadi di sini? Secara spesifik apa yang terakhir sh {}dilakukan? Sepertinya itu hanya ada untuk menenangkan -execperintah find sehingga ada sesuatu yang harus dilakukan, sebuah NOOP.

Saya bisa dengan mudah meletakkannya di echo {}sana dan tampaknya berfungsi dengan baik.

Jawaban:


9

Sintaksnya adalah:

find ... -exec cmd {} +

findakan menemukan sejumlah file berdasarkan kriteria di ...dan dijalankan cmddengan daftar jalur file sebagai argumen, sebanyak mungkin tanpa melampaui batas pada ukuran argumen ke perintah.

Jika perlu dapat membagi daftar file dan memanggil cmdbeberapa kali. Misalnya, ini mungkin berakhir dengan panggilan:

cmd ./file1 ./file2 ... ./file3000
cmd ./file3001 ./file3002 ... ./file4321

Keterbatasan dengan itu adalah yang {}terakhir. Misalnya, Anda tidak dapat menulis:

find ... -exec cmd {} other args +

seperti yang Anda bisa dengan ';'bukan '+'.

Kamu bisa menulis:

find ... -exec echo foo {} +

tapi tidak:

find ... -exec echo {} foo +

Jadi, jika Anda perlu menambahkan beberapa argumen tambahan cmdsetelah daftar file, Anda harus menggunakan shell. (Alasan lain mengapa Anda perlu memanggil shell adalah kapan saja Anda perlu menggunakan fitur shell seperti pengalihan, pipa, beberapa ekspansi string ....)

Dalam sh -c 'inline-script' x a b c, untuk inline-script, $0adalah x, $1adalah a, $2adalah b... demikian "$@"juga daftar 3 argumen: a, b dan c. Jadi di:

find ... -exec sh -c 'cmd "$@" other arg' find-sh {} +

Untuk skrip inline , $0(yang digunakan misalnya saat menampilkan pesan kesalahan) diatur ke find-shdan "$@"merupakan daftar file (apa yang finddiperluas {}ke).

Dengan menggunakan execbuiltin khusus dari shell:

find ... -exec sh -c 'exec cmd "$@" other arg' find-sh {} +

Kami memberi tahu shell untuk tidak melakukan proses tambahan untuk menjalankan cmd, tetapi sebaliknya menjalankannya dalam proses yang sama (mengganti proses shell yang berjalan dengan perintah itu). Beberapa shell suka bash, zshdan beberapa implementasi kshmelakukannya secara implisit untuk perintah terakhir dalam sebuah skrip.


Bisakah Anda menggunakan subkulit alih-alih exec di sana? -exec sh -c '(cmd1; cmd2;)' find-sh {} +?
slm

Jadi jika saya mengerti Anda dengan benar, find-sh {}argumen apa yang ada pada perintah sh -c '...', kan?
slm

@slm, findakan memanggil /bin/shdengan sebagai argumen ("sh", "-c", "...", "find-sh", "./file1", "./file2"...). And inside ... , that maps (the shells maps that) to $ 0` makhluk "find-sh", dan parameter posisi ( $1, $2... yang bisa dibilang adalah argumen untuk naskah inline ) menjadi ./file1, ./file2.
Stéphane Chazelas
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.