Dalam kebanyakan shell nullglob
bukan default. Itu berarti, misalnya, jika Anda menjalankan perintah ini
ls *
dalam direktori kosong, itu akan memperluas *
glob ke literal *
, sebagai gantinya ke daftar argumen kosong. Ada cara untuk mengubah perilaku itu, sehingga *
dalam direktori kosong akan mengembalikan daftar argumen kosong, yang akan tampak lebih intuitif.
Jadi, apakah ada alasan mengapa nullglob
dinonaktifkan secara default? Jika demikian, apa alasannya?
*
adalah gumpalan dan meluas ke semua file yang ada ; bagaimana "intuitif" untuk ada kasus khusus di mana gumpalan direktori kosong "diperluas" ke literal*
?Jawaban:
The
nullglob
pilihan (yang BTW adalahzsh
penemuan, hanya ditambahkan tahun kemudianbash
(2.0
)) tidak akan ideal dalam sejumlah kasus. Danls
merupakan contoh yang bagus:Atau yang setara lebih benar:
Dengan
nullglob
akan berjalanls
tanpa argumen yang diperlakukan sebagails -- .
(daftar direktori saat ini) jika tidak ada file yang cocok, yang mungkin lebih buruk daripada memanggills
dengan*.txt
argumen literal sebagai.Anda akan mengalami masalah serupa dengan sebagian besar utilitas teks:
Akan mencari
foo
di stdin jika tidak adatxt
file.Default yang lebih masuk akal, dan salah satu dari csh, tcsh, zsh atau fish 2.3+ (dan dari shell Unix awal) adalah untuk membatalkan perintah sama sekali jika glob tidak cocok.
bash
(karena versi 3) memilikifailglob
opsi untuk itu (menarik untuk diskusi ini, karena bertentangan denganash
, AT&Tksh
atauzsh
,bash
tidak mendukung cakupan lokal untuk opsi (meskipun itu akan berubah di 4.4), opsi itu ketika diaktifkan secara global tidak merusak beberapa hal. seperti fungsi bash-completion).Perhatikan bahwa csh dan tcsh sedikit berbeda dari
zsh
,fish
ataubash -O failglob
dalam kasus seperti:Di mana Anda membutuhkan semua gumpalan untuk tidak cocok dengan perintah dibatalkan. Misalnya, jika ada satu file txt dan tidak ada file html, itu menjadi:
Anda bisa mendapatkan perilaku yang dengan
zsh
dengansetopt cshnullglob
meskipun cara yang lebih masuk akal untuk melakukannya dizsh
akan menggunakan gumpal seperti:Di
zsh
danksh93
, Anda juga dapat menerapkan nullglob berdasarkan per-glob, yang merupakan pendekatan yang lebih waras daripada memodifikasi pengaturan global:akan membuat array kosong jika tidak ada
txt
file alih-alih gagal perintah dengan kesalahan (atau membuatnya menjadi array dengan satu*.txt
argumen literal dengan shell lain).Versi
fish
sebelum 2.3 akan berfungsi sepertibash -O nullglob
tetapi memberikan peringatan ketika interaktif ketika sebuah gumpal tidak cocok. Sejak 2.3, ini berfungsi sepertizsh
kecuali untuk gumpalan yang digunakan dalamfor
,set
ataucount
.Sekarang, pada catatan sejarah, perilaku itu benar-benar rusak oleh kulit Bourne. Dalam versi Unix sebelumnya, globbing dilakukan melalui
/etc/glob
helper dan helper itu berperilaku seperticsh
: itu akan gagal perintah jika tidak ada gumpalan yang cocok dengan file apa pun dan menghapus gumpalan dengan tidak ada kecocokan sebaliknya.Jadi situasi kita hari ini adalah karena keputusan buruk yang dibuat di kulit Bourne.
Perhatikan bahwa shell Bourne (dan shell C) datang dengan fitur Unix baru lainnya: lingkungan. Itu berarti ekspansi variabel (pendahulunya hanya memiliki
$1
,,$2
... parameter posisi). Shell Bourne juga memperkenalkan substitusi perintah.Keputusan desain lain yang buruk dari shell Bourne adalah untuk melakukan globbing (dan pemisahan) pada ekspansi variabel dan substitusi perintah (mungkin untuk kompatibilitas mundur dengan shell Thompson di mana
echo $1
masih akan memohon/etc/glob
jika$1
berisi wildcard (itu lebih seperti ekspansi makro pra-prosesor di sana, seperti dalam nilai yang diperluas diurai lagi sebagai kode shell)).Kegagalan gumpalan yang tidak cocok akan berarti misalnya bahwa:
akan gagal perintah (kecuali ada beberapa
a.whateverb
file di direktori saat ini).csh
(yang juga melakukan globbing pada ekspansi variabel) tidak gagal perintah dalam kasus itu (dan saya berpendapat itu lebih baik daripada meninggalkan bug aktif di sana, bahkan jika itu tidak sebagus tidak melakukan globbing sama seperti dizsh
).sumber
nullglob
muncul untuk menghancurkan penyelesaian tab (menekan tombol tab tidak melakukan apa-apa saat diaktifkan).files=$(shopt -s nullglob;echo *.txt)
xpg_echo
) menjadi variabel skalar . Anda akan perlu sesuatu sepertireadarray -td '' files < <(shopt -s nullglob; printf '%s\0' *.txt)
denganbash
4.4 atau di atas atau(shopt -s nullglob; printf '%s\0' *.txt) | xargs -r0 cmd
dengan GNUxargs
untuk itu dapat digunakan sama sekali dengan nama file sewenang-wenang. Atau, masih dengan bash4.4, gunakan fungsi pembantu yang menggunakanlocal -
(disalin dari abu 25 tahun kemudian) untuk lingkup lokal untuk opsi.