Perbedaan antara '{}' dan {} dalam perintah find?

18

Dalam dokumentasi , saya melihat penggunaan kedua cara:

find . -type f -exec file '{}' \;

find repo/ -exec test -d {}/.svn -o -d {}/.git -o -d {}/CVS ; \
tarabyte
sumber
4
Tentu sepertinya itu tidak ada hubungannya dengan perintah find, dan sebaliknya berkaitan dengan penawaran yang tepat untuk perintah yang dipanggil.
Zoredache
1
Cobalah dengan ikan, bukan bash.
Charles Duffy

Jawaban:

24

Untuk bashshell, '{}'dan {}dapat dipertukarkan. Ini tidak berlaku untuk semua cangkang (seperti fish).

Menempatkan argumen dalam tanda kutip tunggal secara eksplisit menunjukkan bahwa kurung kurawal harus dikirim ke find. Tergantung pada penggunaan, bash shell kadang-kadang menggantikan isi kurung keriting.

Seperti yang terlihat di bawah, bash tidak menggantikan kurung kosong, dan mereka diteruskan ke perintah. Untuk findperintah, itu tidak masalah.

$ echo {}
{}

$ echo {1}
{1}

$ echo {1,3}
1 3

$ echo '{1,3}'
{1,3}
Steven
sumber
4
Tidak masalah dengan bash. Tidak masalah dengan ikan.
Charles Duffy
1
Saya akan ganti " are interchangeable"dengan " are interchangeable in some shells, not in all of them. ALWAYS use the single quotes to make sure they get passed as-is to the find command"(kebiasaan baik dimulai dengan memastikan Anda menggunakan cara yang benar bahkan jika Anda kebetulan (selalu?) Berada pada sistem yang memungkinkan yang ambigu)
Olivier Dulac
9

Dengan hampir semua penerjemah shell tersedia, sama sekali tidak ada perbedaan antara '{}'dan {}.

Kutipan tunggal biasanya digunakan untuk melindungi string tertanam agar tidak diganti oleh sesuatu yang lain, misalnya:

  • 'a b' adalah parameter tiga karakter tunggal, tanpa tanda kutip yang akan menjadi dua parameter karakter tunggal
  • '$b' adalah tanda dolar yang diikuti oleh huruf b, tanpa tanda kutip yang akan menjadi apa pun yang variabel b berisi dan mungkin tidak ada jika tidak disetel
  • '!!' adalah tanda seru sembarangan tanpa tanda kutip dan dengan beberapa shell interaktif, mereka akan memperluas ke perintah terakhir dimasukkan ke dalam sejarah
  • '*' adalah tanda bintang litteral, tanda kutip itu akan diganti dengan daftar nama file yang tidak tersembunyi di direktori saat ini.

Seperti tidak standar POSIX maupun kerang utama ( sh(Bourne), ksh, bash, ash, dash, zsh, csh, tcsh) memperluas {}ke sesuatu yang lain, tanda kutip tidak diperlukan.

Namun, ada cangkang eksotis, bernama fish, yang kebetulan mengembang {}sebagai string kosong, misalnya:

> ps -p %self
  PID TTY          TIME CMD
 5247 pts/1    00:00:00 fish
> echo a {} b '{}'
a  b {}

Mungkin itulah alasan mengapa finddokumentasi GNU menyarankan untuk melindungi {}dari interpretasi dengan kutipan atau backslash.

Jlliagre
sumber
9

Untuk sebagian besar pengguna (terutama mereka yang menggunakan cangkang POSIX), tidak ada perbedaan.

Menurut bagian Contoh halaman manual untuk GNU find:

Perhatikan bahwa kurung kurawal ditutup dengan tanda kutip tunggal untuk melindunginya dari interpretasi sebagai tanda baca skrip shell.

Saya pikir penulis halaman manual GNU berdosa di sisi hati-hati tapi saya perhatikan bahwa tidak semua contoh di halaman manual mereka mengutip kawat gigi. Contoh - contoh ini dari dokumentasi resmi GNU menemukan juga menghilangkan kutipan.

Dalam contoh - contoh dari POSIX / Single UNIX Spesifikasi kurung kurawal tidak dikutip ketika digunakan dengan -execopsi.

Dengan shell POSIX, ekspansi parameter hanya terjadi ketika ada parameter khusus yang terlampir di dalam kawat gigi - tetapi tidak dengan kawat gigi kosong .

Shell Bash termasuk ekspansi brace sebagai fitur (non-portabel), tetapi pola tersebut hanya diperluas ketika koma atau titik-titik dimasukkan dalam kurung kurawal . Bash juga menggunakan tanda kurung untuk pengelompokan perintah , tetapi ini tidak terjadi kecuali sebenarnya ada sekelompok perintah di dalam tanda kurung.

Akhirnya, saya mencoba menjalankan find -exec ls -l {} \;di sh, dashdan tcshnamun tidak satupun dari kerang ini memperluas {}ke hal lain. Seperti yang telah ditunjukkan orang lain, fishshell memperlakukan {}secara khusus tetapi ini bukan shell POSIX (yang pembuatnya dan penggunanya anggap sebagai keuntungan). Tidak ada salahnya mengutip kawat gigi tetapi juru ketik malas yang tidak menggunakan kerang ikan seharusnya tidak merasa bersalah karena menghilangkannya.

Anthony G - keadilan untuk Monica
sumber
mereka tidak melakukan kesalahan, mereka berusaha memastikan orang menggunakan cara yang benar (yaitu menggunakan '{}'alih-alih {}) sehingga shell mereka mengirim {}ke perintah find tanpa menafsirkannya (seperti disebutkan di atas oleh @ Charles-Duffy, jika Anda kebetulan menggunakan ikan , itu akan menafsirkan {}tetapi tidak '{}', jadi Anda perlu menggunakan yang terakhir pada shell itu (dan pada beberapa yang lain!). Oleh karena itu, selalu gunakan '{}'untuk menghindari digigit oleh ambiguitas{}
Olivier Dulac
6

Ini tergantung pada sintaks shell Anda. Jika ragu, gema!

Jalankan ini

echo '{}'

dan ini.

echo {}

Jika mereka menghasilkan output yang sama, maka jawaban untuk shell Anda adalah ya. Seperti yang telah dicatat oleh orang lain, setidaknya akan ada di bash dan tidak di ikan. Keluarannya, adalah untuk apa Anda harus berkonsultasi dengan halaman perintah yang diberikan.


Jika Anda ingin menjadi berguna, Anda bahkan dapat awalan echoke seluruh baris perintah, untuk melihat perintah yang sebenarnya , dengan semua argumennya, bahwa shell Anda benar-benar akan dipanggil. Namun berhati-hatilah, bahwa daftar yang terdiri dari perintah plus argumen adalah array string yang benar, masing-masing mungkin kosong atau dengan spasi, namun gema mencetaknya secara ambigu sebagai daftar yang dipisahkan oleh ruang.

Seperti dapat diverifikasi dengan perintah gema verbose sedikit lebih ini (menunjukkan argumen yang dikutip guillemet),

#!/bin/sh
for a in "$@"; do
    printf '«%s» ' "$a"
done
echo ''

mengetik ini di baris perintah,

find 'My Documents and Settings' -type f -exec file {} \;

berarti ini untuk bash:

«find» «My Documents and Settings» «-type» «f» «-exec» «file» «{}» «;»

dan ini pada ikan:

«find» «My Documents and Settings» «-type» «f» «-exec» «file» «» «;»

Sebagai saran umum, tidak ada salahnya mengutip.

pengguna2394284
sumber