Saya tahu menggunakan perintah ls
akan mencantumkan semua direktori. Tapi apa ls *
perintah lakukan? Saya menggunakannya dan itu hanya mencantumkan direktori. Apakah bintang di depan ls
berarti seberapa dalam daftar direktori?
Jawaban yang Diterima:
ls
daftar file dan konten direktori yang diteruskan sebagai argumen, dan jika tidak ada argumen yang diberikan, daftar direktori saat ini. Itu juga dapat melewati sejumlah opsi yang memengaruhi perilakunya (lihat man ls
untuk detailnya).
Jika ls
sedang melewati argumen yang disebut *
, itu akan mencari file atau direktori bernama *
di direktori saat ini dan daftarkan sama seperti yang lain. ls
tidak memperlakukan *
karakter dengan cara apa pun selain yang lain.
Namun jika ls *
adalah kulit baris perintah, yaitu kode dalam bahasa shell Unix , maka shell akan memperluas *
menurut globbingnya (juga disebut sebagai Pembuatan Nama File atau Ekspansi Nama File/Nama Jalur ) aturan.
Sementara shell yang berbeda mendukung operator globbing yang berbeda, kebanyakan dari mereka setuju dengan yang paling sederhana *
. *
sebagai pola berarti sejumlah karakter, jadi *
sebagai glob
akan diperluas ke daftar file di direktori saat ini yang cocok dengan pola itu. Namun ada pengecualian bahwa titik awal (.
) karakter dalam nama file harus dicocokkan secara eksplisit, jadi *
sebenarnya meluas ke daftar file dan direktori yang tidak dimulai dengan .
(dalam urutan leksikal).
Misalnya, jika direktori saat ini berisi file yang disebut .
, ..
, .foo
, -l
dan foo bar
, *
akan diperluas oleh shell menjadi dua argumen untuk diteruskan ke ls
:-l
dan foo bar
, jadi seolah-olah Anda telah mengetik:
ls -l "foo bar"
atau
'ls' "-l" foo bar
Yang merupakan tiga cara untuk menjalankan perintah yang persis sama. Dalam semua 3 kasus, ls
perintah (yang mungkin akan dieksekusi dari /bin/ls
dari pencarian direktori yang disebutkan dalam $PATH
) akan melewati 3 argumen tersebut:“ls”, “-l” dan “foo bar”.
Kebetulan, dalam hal ini, ls
akan memperlakukan yang pertama (tepatnya kedua ) satu sebagai opsi.
Sekarang, seperti yang saya katakan, shell yang berbeda memiliki operator globbing yang berbeda. Beberapa dekade yang lalu, zsh
memperkenalkan **/
operator¹ yang berarti mencocokkan semua tingkat subdirektori, kependekan dari (*/)#
dan ***/
yang sama kecuali mengikuti symlink saat menuruni direktori.
Beberapa tahun yang lalu (Juli 2003, ksh93o+
), ksh93
memutuskan untuk menyalin perilaku itu tetapi memutuskan untuk menjadikannya opsional, dan hanya mencakup **
kasus (bukan **
). Juga, saat **
saja tidak istimewa di zsh
² (hanya berarti sama dengan *
seperti pada cangkang tradisional lainnya sejak **
berarti sejumlah karakter diikuti oleh sejumlah karakter), di ksh93, **
artinya sama dengan **/*
(jadi file atau direktori apa pun di bawah yang sekarang (tidak termasuk file tersembunyi)³.
bash
menyalin ksh93
beberapa tahun kemudian (Februari 2009, bash 4.0), dengan sintaks yang sama tetapi perbedaan yang tidak menguntungkan:**
bash seperti zsh
**
, yaitu mengikuti symlink ketika berulang ke sub-direktori yang umumnya bukan yang Anda inginkan dan dapat memiliki efek samping yang buruk. Itu sebagian diperbaiki di bash-4.3 di mana symlink masih diikuti, tetapi rekursi berhenti di sana. Itu sepenuhnya diperbaiki di 5.0.
yash
menambahkan **
di versi 2.0 tahun 2008, diaktifkan dengan extended-glob
pilihan. Implementasinya lebih dekat ke zsh
ada di **
sendiri tidak istimewa. Dalam versi 2.15 (2009), ditambahkan **
seperti di zsh
dan dua ekstensinya sendiri:.**
dan .***
untuk memasukkan direktori tersembunyi saat berulang (dalam zsh
, D
kualifikasi global (seperti dalam **/*(D)
) akan mempertimbangkan file dan direktori tersembunyi, tetapi jika Anda hanya ingin menelusuri direktori tersembunyi tetapi tidak memperluas file tersembunyi, Anda memerlukan ((*|.*)/)#*
atau **/[^.]*(D)
).
Cangkang ikan juga mendukung **
. Seperti versi bash
sebelumnya , ia mengikuti symlink saat menuruni pohon direktori. Namun dalam shell itu **/*
tidak sama dengan **
. **
lebih merupakan perpanjangan dari *
yang dapat menjangkau beberapa direktori. Di fish
, **/*.c
akan cocok dengan a/b/c.c
tapi bukan a.c
, sedangkan a**.c
akan cocok dengan a.c
dan ab/c/d.c
dan zsh
**/.*
misalnya harus ditulis .* **/.*
. Di sana, **
dipahami sebagai **
diikuti oleh *
jadi sama dengan **
.
tcsh
juga menambahkan globstar
opsi di V6.17.01 (Mei 2010) dan mendukung keduanya **
dan **
la zsh
.
Jadi di tcsh
, bash
dan ksh93
, (ketika opsi yang sesuai diaktifkan (globstar
)) atau fish
, **
memperluas semua file dan direktori di bawah yang sekarang, dan **
sama dengan **
untuk fish
, symlink yang melintasi **
untuk tcsh
dengan globstar
, dan sama dengan *
di bash
dan ksh93
(meskipun bukan tidak mungkin bahwa versi mendatang dari shell tersebut juga akan melintasi symlink).
Di atas, Anda akan memperhatikan kebutuhan untuk memastikan tidak ada ekspansi yang ditafsirkan sebagai opsi. Untuk itu, Anda akan melakukan:
ls -- *
Atau:
ls ./*
Ada beberapa perintah (tidak masalah untuk ls
) di mana yang kedua lebih disukai karena bahkan dengan --
beberapa nama file mungkin diperlakukan secara khusus. Ini kasus -
untuk sebagian besar utilitas teks, cd
dan pushd
dan nama file yang mengandung =
karakter untuk awk
misalnya. Mengawali ./
untuk semua argumen menghilangkan arti khusus mereka (setidaknya untuk kasus yang disebutkan di atas).
Perlu juga dicatat bahwa sebagian besar shell memiliki sejumlah opsi yang memengaruhi perilaku globbing (seperti apakah file titik diabaikan atau tidak, urutan penyortiran, apa yang harus dilakukan jika tidak ada yang cocok…), lihat juga $FIGNORE
parameter di ksh
Juga, di setiap shell kecuali csh
, tcsh
, fish
dan zsh
, jika pola globbing tidak cocok dengan file apa pun, pola diteruskan sebagai argumen yang tidak diperluas yang menyebabkan kebingungan dan kemungkinan bug. Misalnya, jika tidak ada file yang tidak disembunyikan di direktori saat ini
ls *
Akan benar-benar memanggil ls
dengan dua argumen ls
dan *
. Dan karena tidak ada file sama sekali, jadi tidak ada yang disebut *
baik, Anda akan melihat pesan kesalahan dari ls (bukan shell) seperti:ls: cannot access *: No such file or directory
, yang telah diketahui membuat orang berpikir bahwa itu adalah ls
yang sebenarnya memperluas gumpalan.
Masalahnya bahkan lebih buruk dalam kasus-kasus seperti:
rm -- *.[ab]
Jika tidak ada *.a
atau *.b
file di direktori saat ini, maka Anda mungkin akan menghapus file bernama *.[ab]
karena kesalahan (csh
, tcsh
, dan zsh
akan melaporkan tidak cocok kesalahan dan tidak akan memanggil rm
(dan fish
tidak mendukung [...]
wildcard)).
Jika Anda ingin melewatkan *
liter literal ke ls
, Anda harus mengutip *
. itu karakter dalam beberapa cara seperti dalam ls *
atau ls '*'
atau ls "*"
. Dalam shell seperti POSIX, globbing dapat dinonaktifkan sama sekali menggunakan set -o noglob
atau set -f
(yang terakhir tidak berfungsi di zsh
kecuali di sh
/ksh
emulasi).
.