Saya menemukan diri saya terus mencari sintaks
find . -name "FILENAME" -exec rm {} \;
terutama karena saya tidak melihat bagaimana tepatnya -exec
bagian itu berfungsi. Apa arti dari kawat gigi, garis miring terbalik dan titik koma? Apakah ada kasus penggunaan lain untuk sintaksis itu?
man
halaman POSIX lama membaca Utilitas_name atau argumen yang hanya mengandung dua karakter "{}" harus diganti oleh pathname saat ini , yang tampaknya cukup bagi saya. Selain itu memiliki contoh dengan-exec rm {} \;
, seperti dalam pertanyaan Anda. Di masa saya, hampir tidak ada sumber daya lain selain "tembok abu-abu besar", buku-bukuman
halaman yang dicetak (kertas lebih ceper daripada penyimpanan). Jadi saya tahu bahwa ini cukup untuk seseorang yang baru dalam topik ini. Namun pertanyaan terakhir Anda cukup adil untuk ditanyakan di sini. Sayangnya @Kusalananda maupun saya sendiri tidak punya jawaban untuk itu.xargs
terkadang berguna,find
dapat melewati beberapa argumen jalur untuk memerintahkan tanpa itu.-exec command... {} +
(dengan+
bukannya\;
) melewati banyak jalur setelahcommand...
sesuai (masing-masing OS memiliki batas sendiri pada berapa lama baris perintah dapat). Dan sepertixargs
, yang+
bentuk -terminated darifind
's-exec
tindakan juga akan berjalancommand...
beberapa kali dalam kasus yang jarang terjadi bahwa ada terlalu banyak jalan agar sesuai dalam batas.Jawaban:
Jawaban ini datang di bagian berikut:
-exec
-exec
dalam kombinasi dengansh -c
-exec ... {} +
-execdir
Penggunaan dasar
-exec
The
-exec
pilihan mengambil utilitas eksternal dengan argumen opsional sebagai argumen dan mengeksekusi itu.Jika string
{}
ada di mana saja dalam perintah yang diberikan, setiap instance akan digantikan oleh pathname yang saat ini sedang diproses (misalnya./some/path/FILENAME
). Dalam kebanyakan shell, kedua karakter{}
tidak perlu dikutip.Perintah perlu diakhiri dengan
;
untukfind
mengetahui di mana ia berakhir (karena mungkin ada opsi lebih lanjut setelah itu). Untuk melindungi;
shell, shell harus dikutip sebagai\;
atau';'
, jika tidak shell akan melihatnya sebagai akhir darifind
perintah.Contoh (
\
pada akhir dua baris pertama hanya untuk kelanjutan baris):Ini akan menemukan semua file biasa (
-type f
) yang namanya cocok dengan pola*.txt
di atau di bawah direktori saat ini. Kemudian akan menguji apakah stringhello
terjadi di salah satu file yang ditemukan menggunakangrep -q
(yang tidak menghasilkan output apa pun, hanya status keluar). Untuk file-file yang berisi string,cat
akan dieksekusi untuk menampilkan isi file ke terminal.Masing-masing
-exec
juga bertindak seperti "tes" pada nama path yang ditemukan olehfind
, sama seperti-type
dan-name
tidak. Jika perintah mengembalikan status keluar nol (menandakan "sukses"), bagian selanjutnya darifind
perintah dipertimbangkan, jika tidak,find
perintah akan dilanjutkan dengan nama path berikutnya. Ini digunakan dalam contoh di atas untuk menemukan file yang berisi stringhello
, tetapi untuk mengabaikan semua file lainnya.Contoh di atas menggambarkan dua kasus penggunaan paling umum
-exec
:find
perintah).Menggunakan
-exec
dalam kombinasi dengansh -c
Perintah yang
-exec
dapat dieksekusi terbatas pada utilitas eksternal dengan argumen opsional. Untuk menggunakan built-in shell, fungsi, kondisional, jalur pipa, pengalihan dll secara langsung dengan-exec
tidak dimungkinkan, kecuali dibungkus dengan sesuatu sepertish -c
shell anak.Jika
bash
fitur diperlukan, maka gunakanbash -c
di tempatsh -c
.sh -c
berjalan/bin/sh
dengan skrip yang diberikan pada baris perintah, diikuti oleh argumen baris perintah opsional untuk skrip itu.Contoh sederhana penggunaannya
sh -c
sendiri, tanpafind
:Ini meneruskan dua argumen ke skrip shell anak:
String
sh
. Ini akan tersedia sebagai$0
di dalam skrip, dan jika shell internal menampilkan pesan kesalahan, ia akan awalan dengan string ini.Argumen
apples
tersebut tersedia seperti$1
dalam skrip, dan jika ada lebih banyak argumen, maka ini akan tersedia sebagai$2
,$3
dll. Mereka juga akan tersedia dalam daftar"$@"
(kecuali$0
yang tidak akan menjadi bagian dari"$@"
).Ini berguna dalam kombinasi dengan
-exec
karena memungkinkan kita untuk membuat skrip kompleks yang bertindak sewenang-wenang pada nama path yang ditemukan olehfind
.Contoh: Temukan semua file biasa yang memiliki akhiran nama file tertentu, dan ubah akhiran nama file itu ke beberapa akhiran lainnya, di mana akhiran disimpan dalam variabel:
Di dalam skrip internal,
$1
akan menjadi stringtext
,$2
akan menjadi stringtxt
dan$3
akan menjadi apa pun pathname yangfind
ditemukan untuk kita. Ekspansi parameter${3%.$1}
akan mengambil pathname dan menghapus akhiran.text
darinya.Atau, menggunakan
dirname
/basename
:atau, dengan variabel yang ditambahkan di skrip internal:
Perhatikan bahwa dalam variasi terakhir ini, variabel
from
danto
di shell anak berbeda dari variabel dengan nama yang sama di skrip eksternal.Di atas adalah cara yang benar memanggil script kompleks sewenang-wenang dari
-exec
denganfind
. Menggunakanfind
dalam lingkaran sepertirentan terhadap kesalahan dan tidak tangguh (pendapat pribadi). Ini adalah pemisahan nama file pada spasi putih, memanggil globbing nama file, dan juga memaksa shell untuk memperluas hasil lengkap
find
sebelum bahkan menjalankan iterasi pertama dari loop.Lihat juga:
Menggunakan
-exec ... {} +
Pada
;
akhirnya dapat diganti dengan+
. Ini menyebabkanfind
untuk mengeksekusi perintah yang diberikan dengan sebanyak mungkin argumen (ditemukan nama path) daripada satu untuk setiap nama path yang ditemukan. String{}
harus terjadi tepat sebelum+
ini berfungsi .Di sini,
find
akan mengumpulkan nama path yang dihasilkan dan mengeksekusicat
pada sebanyak mungkin dari mereka sekaligus.Demikian juga di sini,
mv
akan dieksekusi beberapa kali mungkin. Contoh terakhir ini membutuhkan GNUmv
dari coreutils (yang mendukung-t
opsi).Menggunakan
-exec sh -c ... {} +
juga merupakan cara yang efisien untuk mengulang set nama path dengan skrip yang sewenang-wenang.Dasar-dasarnya sama dengan ketika menggunakan
-exec sh -c ... {} ';'
, tetapi skrip sekarang membutuhkan daftar argumen yang jauh lebih lama. Ini dapat diulang dengan mengulang"$@"
di dalam skrip.Contoh kami dari bagian terakhir yang mengubah akhiran nama file:
Menggunakan
-execdir
Ada juga
-execdir
(diimplementasikan oleh sebagian besarfind
varian, tetapi bukan opsi standar).Ini berfungsi seperti
-exec
dengan perbedaan bahwa perintah shell yang diberikan dieksekusi dengan direktori pathname yang ditemukan sebagai direktori kerjanya saat ini dan itu{}
akan berisi nama samaran dari pathname yang ditemukan tanpa pathnya (tetapi GNUfind
masih akan awalan dengan nama basenya./
, sementara BSDfind
tidak akan melakukan itu).Contoh:
Ini akan memindahkan setiap
*.txt
file -file yang ditemukan kedone-texts
subdirektori yang sudah ada di direktori yang sama dengan tempat file ditemukan . File juga akan diganti namanya dengan menambahkan akhiran.done
ke dalamnya.Ini akan sedikit lebih sulit untuk dilakukan
-exec
karena kita harus mengeluarkan nama file dari file yang ditemukan{}
untuk membentuk nama file yang baru. Kami juga memerlukan nama direktori dari{}
untuk menemukandone-texts
direktori dengan benar.Dengan
-execdir
, beberapa hal seperti ini menjadi lebih mudah.Operasi yang sesuai menggunakan
-exec
alih-alih-execdir
harus menggunakan shell anak:atau,
sumber
-exec
mengambil program dan argumen dan menjalankannya; beberapa perintah shell hanya terdiri dari program dan argumen tetapi banyak yang tidak. Perintah shell dapat mencakup pengalihan dan perpipaan;-exec
tidak dapat (meskipun keseluruhanfind
dapat dialihkan). Perintah shell dapat menggunakan; && if
dll;-exec
tidak bisa, walaupun-a -o
bisa melakukan beberapa. Perintah shell bisa berupa fungsi alias atau shell, atau builtin;-exec
tidak bisa. Perintah shell dapat memperluas vars;-exec
tidak dapat (meskipun kulit terluar yang menjalankanfind
kaleng). Perintah shell dapat menggantikan secara$(command)
berbeda setiap kali;-exec
tidak bisa. ...-exec
tidak bisa - meskipunfind
dapat beralih di atas file dengan cara yang sama seperti kebanyakan glob, jadi itu jarang diinginkan.sh
dirinya sendiri, yang sepenuhnya mampu melakukan semua halfind -exec cmd arg \;
tidak meminta shell untuk menginterpretasikan baris perintah shell, itu berjalanexeclp("cmd", "arg")
langsung, bukanexeclp("sh", "-c", "cmd arg")
(yang shell akhirnya akan melakukan yang setara denganexeclp("cmd", "arg")
jikacmd
tidak dibangun).find
argumen setelah-exec
dan hingga;
atau+
membuat perintah untuk mengeksekusi bersama dengan argumennya, dengan setiap instance{}
argumen diganti dengan file saat ini (dengan;
), dan{}
sebagai argumen terakhir sebelum+
diganti dengan daftar file sebagai argumen terpisah (dalam{} +
kasus ini). TKI-exec
mengambil beberapa argumen, diakhiri oleh a;
atau{}
+
.