The nullglob
pilihan (yang BTW adalah zsh
penemuan, hanya ditambahkan tahun kemudian bash
( 2.0
)) tidak akan ideal dalam sejumlah kasus. Dan ls
merupakan contoh yang bagus:
ls *.txt
Atau yang setara lebih benar:
ls -- *.txt
Dengan nullglob
akan berjalan ls
tanpa argumen yang diperlakukan sebagai ls -- .
(daftar direktori saat ini) jika tidak ada file yang cocok, yang mungkin lebih buruk daripada memanggil ls
dengan *.txt
argumen literal sebagai.
Anda akan mengalami masalah serupa dengan sebagian besar utilitas teks:
grep foo *.txt
Akan mencari foo
di stdin jika tidak ada txt
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) memiliki failglob
opsi untuk itu (menarik untuk diskusi ini, karena bertentangan dengan ash
, AT&T ksh
atau zsh
, 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
atau bash -O failglob
dalam kasus seperti:
ls -- *.txt *.html
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:
ls -- file.txt
Anda bisa mendapatkan perilaku yang dengan zsh
dengan setopt cshnullglob
meskipun cara yang lebih masuk akal untuk melakukannya di zsh
akan menggunakan gumpal seperti:
ls -- *.(txt|html)
Di zsh
dan ksh93
, Anda juga dapat menerapkan nullglob berdasarkan per-glob, yang merupakan pendekatan yang lebih waras daripada memodifikasi pengaturan global:
files=(*.txt(N)) # zsh
files=(~(N)*.txt) # ksh93
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 seperti bash -O nullglob
tetapi memberikan peringatan ketika interaktif ketika sebuah gumpal tidak cocok. Sejak 2.3, ini berfungsi seperti zsh
kecuali untuk gumpalan yang digunakan dalam for
, set
atau count
.
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 seperti csh
: 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:
pattern='a.*b'
grep $pattern file
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 di zsh
).