Apa artinya "{} \;" dalam perintah find?

38

Terkadang saya melihat perintah berikut:

find . -name  * -exec ls -a {} \;

Saya diminta untuk mengeksekusi ini.

Apa yang dimaksud di {} \;sini?

kode kode
sumber
2
-name *berlebihan.
Kevin
3
Lihat juga penjelasan tentang jenis pertanyaan lain seperti ini. Inilah output untuk perintah Anda. .
Glutanimate
10
-name *lebih buruk dari mubazir. Karena tanda *kutip tidak dikutip, shell memperluasnya ke daftar nama file di folder saat ini, dengan ruang-ruang yang salah dirawat, mengarah ke hasil yang tidak terduga atau pesan kesalahan. Sebagai tambahan, findmemiliki banyak fungsi, salah satunya adalah membuat daftar file; ini menghindari penggunaan -exec. Misalnya, Anda dapat menggunakan find . -printatau find . -ls. Akhirnya, ada dua cara untuk melarikan diri semi-colon: baik seperti yang Anda lakukan dengan garis miring terbalik, \;atau dengan mengutip: ';'. Gunakan mana pun yang Anda merasa lebih nyaman.
Paddy Landau

Jawaban:

49

Jika Anda menjalankan finddengan exec, {}memperluas untuk nama file dari setiap file atau direktori yang ditemukan dengan find(sehingga lsdalam contoh Anda mendapatkan setiap nama file berhasil ditemukan sebagai argumen - catatan bahwa panggilan lsatau apa pun perintah lain yang Anda tentukan sekali untuk setiap file ditemukan).

Titik koma ;mengakhiri perintah yang dijalankan oleh exec. Itu perlu melarikan diri dengan \sehingga shell yang Anda jalankan finddi dalam tidak memperlakukannya sebagai karakter khusus sendiri, tetapi meneruskannya ke find.

Lihat artikel ini untuk lebih jelasnya.


Juga, findberikan beberapa optimasi dengan exec cmd {} +- ketika dijalankan seperti itu, findmenambahkan file yang ditemukan ke akhir perintah daripada memanggilnya satu kali per file (sehingga perintah dijalankan hanya sekali, jika mungkin).

Perbedaan perilaku (jika tidak efisiensi) mudah terlihat jika dijalankan dengan ls, misalnya

find ~ -iname '*.jpg' -exec ls {} \;
# vs
find ~ -iname '*.jpg' -exec ls {} +

Dengan asumsi Anda memiliki beberapa jpgfile (dengan jalur yang cukup pendek ), hasilnya adalah satu baris per file dalam kasus pertama dan lsperilaku standar menampilkan file dalam kolom untuk yang terakhir.

moon.musick
sumber
1
Saya pikir itu akan bermanfaat bagi Anda untuk kontras \;dengan +.
Kevin
Bagaimana bedanya find . -name * | ls -a -?
András Hummer
@ DrH Intinya bukan untuk membiarkan shell melakukan ekspansi wildcard melainkan meneruskan ekspresi wildcard find. Juga, output lsdalam hal ini tampaknya tidak bergantung pada input - tidak peduli apa yang saya gunakan sebagai filter find, lshanya menampilkan konten direktori yang berfungsi dan itu saja. Periksa misalnya find ~ -iname '*.jpg' -exec ls -a {} \;vs find ~ -iname '*.jpg' | ls -a.
moon.musick
@RH atau genap echo 'foo' | ls -a.
moon.musick
@ moon.musick, saya yakin Anda telah melewatkan hal penting -dalam ls -a -perintah Anda saat menguji apa yang dilakukan @ dr-h.
Daniel Llewellyn
21

Dari halaman manual untuk findperintahIkon halaman manual :

-exec command ;
              Execute  command;  true if 0 status is returned.  All following arguments to find are taken to be arguments to
              the command until an argument consisting of `;' is encountered.  The string `{}' is replaced  by  the  current
              file name being processed everywhere it occurs in the arguments to the command, not just in arguments where it
              is alone, as in some versions of find.  Both of these constructions might need to be escaped (with a  `\')  or
              quoted  to  protect them from expansion by the shell.

Jadi, inilah penjelasannya:

{}berarti "output dari find". Seperti dalam, "apa pun yang findditemukan". findmengembalikan jalur file yang Anda cari, kan? Jadi {}gantikan itu; itu adalah penampung untuk setiap file yang ditemukan oleh findperintah (diambil dari sini ).

Bagian \;ini pada dasarnya mengatakan find"oke, saya sudah selesai dengan perintah yang ingin saya jalankan".

Contoh:

Katakanlah saya berada di direktori yang penuh dengan .txtfile. Saya kemudian menjalankan:

find . -name  '*.txt' -exec cat {} \;

Bagian pertama find . -name *.txt,, mengembalikan daftar .txtfile. Bagian kedua, -exec cat {} \;akan mengeksekusi catperintah untuk setiap file ditemukan oleh find, jadi cat file1.txt, cat file2.txt, dan sebagainya.

Alaa Ali
sumber
4
Bagian *.txtharus dikutip sebagai '*.txt'. Ini karena jika ada .txtfile di folder saat ini, shell akan memperluas ini dan Anda akan mendapatkan hasil yang salah atau pesan kesalahan. find -name '*.txt' -exec cat {} \;
Paddy Landau
@Alaa Ali menjelaskan dengan sangat baik
pushya