Halaman manual untuk GNU find state:
-exec command ; [...] 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.
Itu dari man to find
(GNU findutils) 4.4.2.
Sekarang saya menguji ini dengan bash dan dash, dan keduanya tidak perlu memiliki {}
topeng. Berikut ini adalah tes sederhana:
find /etc -name "hosts" -exec md5sum {} \;
Apakah ada shell, yang saya benar-benar perlu untuk menutupi kawat gigi? Perhatikan, itu tidak tergantung pada apakah file yang ditemukan berisi kosong (dipanggil dari bash):
find ~ -maxdepth 1 -type d -name "U*" -exec ls -d {} \;
/home/stefan/Ubuntu One
Ini berubah jika file yang ditemukan diteruskan ke subkulit:
find ~ -maxdepth 3 -type d -name "U*" -exec bash -c 'ls -d {}' \;
ls: cannot access /home/stefan/Ubuntu: No such file or directory
ls: cannot access One: No such file or directory
yang dapat diselesaikan dengan:
find ~ -maxdepth 3 -type d -name "U*" -exec bash -c 'ls -d "$0"' {} \;
berlawanan dengan:
find ~ -maxdepth 3 -type d -name "U*" -exec bash -c 'ls -d "{}"' \;
/home/stefan/Ubuntu One
tapi bukan itu yang dibicarakan oleh halaman manual, bukan? Jadi cangkang mana yang memperlakukan {}
dengan cara yang berbeda?
Jawaban:
Rangkuman : Jika pernah ada shell yang mengembang
{}
, itu benar-benar barang lawas sekarang.Dalam cangkang Bourne dan cangkang yang sesuai dengan POSIX, kurung kurawal (
{
dan}
) adalah karakter biasa (tidak seperti(
dan)
yang merupakan pembatas kata seperti;
dan&
, dan[
dan]
yang merupakan penggumpalan karakter). Semua string berikut seharusnya dicetak secara literal:Sebuah kata yang terdiri dari penjepit tunggal adalah kata yang dipesan , yang hanya khusus jika itu adalah kata pertama dari suatu perintah.
Ksh mengimplementasikan ekspansi brace sebagai ekstensi yang tidak kompatibel ke shell Bourne. Ini bisa dimatikan dengan
set +B
. Bash mengemulasi ksh dalam hal ini. Zsh mengimplementasikan ekspansi brace juga; ada itu dapat dimatikan denganset +I
atausetopt ignore_braces
atauemulate sh
. Tak satu pun dari cangkang ini mengembang{}
dalam hal apa pun, bahkan ketika itu adalah substring dari sebuah kata (misalnyafoo{}bar
), karena penggunaan umum dalam argumen kefind
danxargs
.Single Unix v2 mencatat itu
Catatan ini dijatuhkan dalam versi standar berikutnya; yang contoh untuk
find
memiliki kegunaan kuotasi dari{}
, seperti melakukan contoh untukxargs
. Mungkin ada kerang Bourne historis di mana{}
harus dikutip, tetapi mereka akan menjadi sistem warisan yang benar-benar tua sekarang.Implementasi csh saya harus di tangan (OpenBSD 4.7, BSD csh pada Debian , tcsh) semua memperluas
{foo}
kefoo
tetapi meninggalkan{}
sendirian.sumber
bash
(lihat$BASH_VERSION
). Ekspansi brace sangat hidup dan sehat.{}
sintaks berasalcsh
, tetapi{}
diperluas ke string kosong. Kerang yang lebih baru mengakui bahwa itu tidak masuk akal, tetapi masih ada beberapa yang lamacsh
di luar sana.{}foo
akan memperluas kefoo
, tetapi{}
akan memperluas ke{}
(kecuali ketika dalam backticks, tetapi mengutip tidak akan membantu) dan didokumentasikan seperti itu. Saya memverifikasi untuk csh dari 2BSD (rilis pertama), 2.79BSD, 2.8BSD dan 2.11BSD.Yang
{}
perlu dikutip dalam versifish
shell sebelum 3.0.0.Dan di shell rc (juga
akanga
didasarkan padarc
, tetapi tidakes
):Itu mungkin bukan shell yang penulis GNU temukan dalam pikiran ketika mereka menulis teks
fish
itu sejak pertama kali dirilis pada 2005 (sementara teks atau sejenisnya sudah ada pada 1994) danrc
pada awalnya bukan shell Unix.Ada beberapa rumor tentang beberapa versi
csh
(shell yang memperkenalkan brace expansion) yang membutuhkannya. Tetapi sulit untuk memberikan kredit kepada mereka sejak rilis pertamacsh
di 2BSD tidak. Di sini seperti yang diuji dalam emulator PDP11:Dan halaman manual dari 2BSD
csh
dengan jelas menyatakan :Jadi saya akan merasa sangat aneh jika versi selanjutnya dari csh atau tcsh kemudian memecahkannya.
Bisa jadi untuk mengatasi beberapa bug dalam beberapa versi. Masih dengan 2BSD csh (sama dengan 2.79BSD, 2.8BSD, 2.11BSD):
Mengutip tidak membantu:
Anda bisa mengutip seluruh substitusi perintah:
Tapi itu melewati satu argumen ke gema luar itu.
Di
csh
atautcsh
, Anda harus mengutip{}
ketika tidak sendiri seperti di:(Meskipun
find
penggunaan semacam itu tidak portabel karena beberapafind
s hanya berkembang{}
ketika sendiri).sumber
Dalam satu kata
csh
,.bash
dan shell modern lainnya mengakui bahwa pengguna mungkin tidak meminta ekspansi penjepit nol. (Moderncsh
sebenarnyatcsh
dan mungkin juga menangani{}
dengan waras sekarang.)sumber
csh
. Tidak semua orang menjalankan utilitas GNU di Linux; sebenarnya itu cukup umum untuk menginstalnya pada sistem Unix komersial yang lebih tua yang perintah bundelnya terbatas. (Mengganticsh
sistem-sistem itu lebih kecil kemungkinannya, karena skrip-skrip sistem mungkin mengandalkan keanehan dari dokumen aslicsh
, dan bahkan jika semua pengguna dikonfigurasikan untuk menggunakan yang lebih barucsh
,root
hampir pasti harus tetap menggunakan versi yang dibundel.)pdksh
melakukan hal yang benar ... walaupun jawaban yang benar untuk itu mungkin "nyataksh
adalah FOSS hari ini"...
untuk ksh93, bash dan zsh). Hanya (t) csh mengembang{foo}
kefoo
, dan bahkan ia meninggalkan{}
saja (setidaknya pada baru-baru BSD).