Saya tahu menggunakan perintah ls
akan mencantumkan semua direktori. Tetapi apa yang dilakukan ls *
perintah itu? Saya menggunakannya dan itu hanya daftar direktori. Apakah bintang di depan ls
berarti seberapa dalam ia dapat mendaftar direktori?
ls
daftar file dan isi direktori yang dilewatkan 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
detailnya).
Jika ls
sedang melewati argumen yang disebut *
, itu akan mencari file atau direktori yang dipanggil *
dalam direktori saat ini dan daftar seperti yang lain. ls
tidak memperlakukan *
karakter dengan cara lain selain yang lain.
Namun jika ls *
adalah baris perintah shell , maka shell akan memperluas yang *
sesuai dengan globbing shell yang sesuai (juga disebut sebagai Generasi Nama File atau Perluasan Nama File ).
Sementara cangkang yang berbeda mendukung operator globbing yang berbeda, kebanyakan dari mereka menyetujui yang paling sederhana *
. *
sebagai pola berarti jumlah karakter, sehingga *
sebagai glob
akan memperluas ke daftar file dalam direktori saat ini yang cocok dengan pola itu. Namun ada pengecualian bahwa karakter titik ( .
) di nama file harus dicocokkan secara eksplisit, jadi *
sebenarnya diperluas ke daftar file dan direktori yang tidak dimulai dengan .
(dalam urutan leksikografis).
Misalnya, jika direktori saat ini berisi file yang disebut .
, ..
, .foo
, -l
dan foo bar
, *
akan diperluas oleh shell untuk dua argumen untuk lolos ke ls
: -l
dan foo bar
, sehingga akan menjadi seperti jika Anda telah mengetik:
ls -l "foo bar"
atau
'ls' "-l" foo\ bar
Yang mana tiga cara untuk menjalankan perintah yang persis sama. Dalam semua 3 kasus, ls
perintah (yang mungkin akan dieksekusi dari /bin/ls
pencarian direktori yang disebutkan dalam $PATH
) akan melewati 3 argumen: "ls", "-l" dan "foo bar".
Kebetulan, dalam hal ini, ls
akan memperlakukan yang pertama (secara tegas kedua ) sebagai pilihan.
Sekarang, seperti yang saya katakan, shell yang berbeda memiliki operator globbing yang berbeda. Beberapa dekade yang lalu, zsh
memperkenalkan **/
operator¹ yang berarti untuk mencocokkan setiap tingkat subdirektori, kependekan dari (*/)#
dan ***/
yang sama kecuali bahwa ia mengikuti symlinks saat turun direktori.
Beberapa tahun yang lalu (Juli 2003, ksh93o+
), ksh93
memutuskan untuk menyalin perilaku itu tetapi memutuskan untuk menjadikannya opsional, dan hanya membahas **
kasus (tidak ***
). Juga, sementara **
sendirian tidak istimewa zsh
(hanya berarti sama *
seperti di shell tradisional lainnya karena **
berarti sejumlah karakter diikuti oleh sejumlah karakter), di ksh93, **
berarti sama dengan **/*
(sehingga file atau direktori di bawah yang sekarang) (tidak termasuk file tersembunyi).
bash
disalin ksh93
beberapa tahun kemudian (Februari 2009, bash 4.0), dengan sintaksis yang sama tetapi perbedaan yang disayangkan: bash's **
seperti zsh
's ***
, yaitu mengikuti symlink ketika berulang ke sub-direktori yang umumnya tidak seperti yang Anda inginkan dan dapat memiliki efek samping yang buruk. Itu sebagian diperbaiki di bash-4.3 bahwa symlink masih diikuti, tetapi rekursi berhenti di sana. Itu sepenuhnya diperbaiki di 5.0.
yash
ditambahkan **
dalam versi 2.0 pada 2008, diaktifkan dengan extended-glob
opsi. Implementasinya lebih dekat dengan zsh
itu **
saja tidak istimewa. Dalam versi 2.15 (2009), ia menambahkan ***
seperti dalam zsh
dan dua ekstensi sendiri: .**
dan .***
untuk memasukkan dir tersembunyi ketika berulang (dalam zsh
, D
kualifikasi glob (seperti dalam **/*(D)
) akan mempertimbangkan file dan direktori tersembunyi, tetapi jika Anda hanya ingin melintasi tersembunyi dir tetapi tidak memperluas file tersembunyi, Anda perlu ((*|.*)/)#*
atau **/[^.]*(D)
).
The shell ikan juga mendukung **
. Seperti versi sebelumnya bash
, ia mengikuti symlink ketika turun pohon direktori. Namun dalam shell **/*
itu tidak sama dengan **
. **
lebih merupakan perpanjangan dari *
yang dapat menjangkau beberapa direktori. Dalam fish
, **/*.c
akan cocok a/b/c.c
tetapi tidak a.c
, sementara a**.c
akan cocok a.c
dan ab/c/d.c
dan zsh
's **/.*
misalnya harus ditulis .* **/.*
. Di sana, ***
dipahami sebagai **
diikuti oleh *
sama dengan **
.
tcsh
juga menambahkan globstar
opsi di V6.17.01 (Mei 2010) dan mendukung keduanya **
dan ***
à la zsh
.
Jadi dalam tcsh
, bash
dan ksh93
, (ketika opsi yang sesuai diaktifkan ( globstar
)) atau fish
, **
memperluas semua file dan direktori di bawah satu saat, dan ***
adalah sama seperti **
untuk fish
, symlink melintasi **
untuk tcsh
dengan globstar
, dan sama seperti *
di bash
dan ksh93
(meskipun itu bukan tidak mungkin bahwa versi masa depan dari shell tersebut juga akan melintasi symlinks).
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 dapat diperlakukan secara khusus. Ini merupakan kasus -
untuk sebagian besar utilitas teks, cd
dan pushd
dan nama file yang mengandung =
karakter awk
misalnya. Bergantung ./
pada semua argumen menghilangkan makna khusus mereka (setidaknya untuk kasus yang disebutkan di atas).
Perlu juga dicatat bahwa kebanyakan shell memiliki sejumlah opsi yang memengaruhi perilaku globbing (seperti apakah file dot diabaikan atau tidak, urutan pengurutan, apa yang harus dilakukan jika tidak ada kecocokan ...), lihat juga $FIGNORE
parameter dalamksh
Juga, di setiap shell tetapi csh
, tcsh
, fish
dan zsh
, jika pola globbing tidak cocok file apapun, pola dilewatkan sebagai argumen unexpanded yang menyebabkan kebingungan dan mungkin bug. Misalnya, jika tidak ada file tidak tersembunyi di direktori saat ini
ls *
Akan benar-benar memanggil ls
dengan dua argumen ls
dan *
. Dan karena tidak ada file sama sekali, sehingga 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 ls
sebenarnya yang memperluas gumpalan.
Masalahnya bahkan lebih buruk dalam kasus-kasus seperti:
rm -- *.[ab]
Jika tidak ada *.a
atau *.b
file dalam direktori saat ini, maka Anda mungkin berakhir menghapus file yang disebut *.[ab]
oleh kesalahan ( csh
, tcsh
, dan zsh
akan melaporkan tidak cocok kesalahan dan tidak akan menyebut rm
(dan fish
tidak mendukung [...]
wildcard)).
Jika Anda ingin meneruskan suatu literal *
ke ls
, Anda harus mengutip *
karakter itu dalam beberapa cara seperti dalam ls \*
atau ls '*'
atau ls "*"
. Dalam cangkang mirip POSIX, globbing dapat dinonaktifkan sama sekali menggunakan set -o noglob
atau set -f
(yang terakhir tidak berfungsi zsh
kecuali dalam sh
/ ksh
emulation).
¹ Meskipun (*/)#
selalu didukung, pertama kali menggunakan tangan pendek seperti ..../
pada zsh-2.0 (dan berpotensi sebelum), kemudian ****/
pada 2.1 sebelum mendapatkan bentuk definitifnya **/
di 2.2 (awal 1992)
find -name *
. Terutama dengan pola yang lebih kompleks, jika ada satu kecocokan di direktori saat ini, orang-orang akan sering tidak menyadari bahwa mereka tidak memberikan tanda bintangfind
.*.[ab]
akan mencoba untuk menghapus semua yang diakhiri dengan.[ab]
.[
tidak istimewa pada ikan.Perintah
ls
default untukls .
: Daftar semua entri dalam direktori saat ini .Perintah itu
ls *
berarti 'jalankan ls pada perluasan*
pola shell'The
*
Pola diproses oleh shell, dan memperluas ke semua entri dalam direktori saat ini, kecuali mereka yang memulai dengan.
. Ini akan naik satu level.Interpretasi
*
pola double atau triple tergantung pada shell aktual yang digunakan.*
adalah wildcard yang cocok dengan 0 karakter atau lebih. Beberapa shell modern akan muncul kembali menjadi subdirektori saat melihat**
polanya.sumber
*
melakukan menambahkan sesuatu, lihat jawaban lain menjelaskan globstar tersebut. Harus juga diperjelas bahwa tidak ada hubungannya dengan tanda bintang, tidak pernah melewati tanda bintang ini sama sekali. Jalankanecho ls *
untuk melihat apa yang akan dieksekusi ketika Anda menulisls *
.Anda dapat menghilangkan mitos seluruh proses dengan mengetik
echo
alih-alihls
terlebih dahulu, untuk melihat apa yang diperlebar perintah:Jadi dalam hal ini,
ls *
perluasls Applications Downloads Documents tmp.html
Jadi tidak ada perubahan. Ini mengasumsikan Anda menggunakan
bash
shell Anda - kebanyakan orang, dan shell berbeda memiliki perilaku yang berbeda. Jika Anda menggunakanash
ataucsh
atauksh
atauzsh
, Anda mungkin mengharapkan berbagai hal bekerja secara berbeda. Itulah gunanya memiliki cangkang yang berbeda.Jadi mari kita coba sesuatu yang berbeda (masih dengan
bash
) sehingga kita mendapatkan gagasan tentang*
operator globbing ( ) dapat lakukan untuk kita. Misalnya, kita dapat memfilter berdasarkan nama:Dan yang menarik, garis miring adalah bagian yang tersirat dari nama direktori. Jadi
*/
hanya akan menghasilkan direktori (dan tautan simbolik ke direktori):Dan kita bisa melakukan beberapa penyaringan di beberapa level dengan meletakkan garis miring di tengah:
Karena
Downloads
direktori tidak mengandung subdirektori apa pun, itu tidak berakhir pada output. Ini sangat berguna untuk hanya memeriksa file yang Anda inginkan. Saya menggunakan perintah seperti ini setiap saat:Daftar ini, jika ada, semua
wp-config.php
file yang ada di tingkat dasarpublic_html
direktori pengguna mana pun . Atau mungkin lebih lengkap:Ini akan menemukan
wp-config.php
file dalam setiap penggunapublic_html
direktori atau subdirektori mereka, tetapi akan beroperasi lebih efisien daripada hanyafind /home/ -name wp-config.php
karena tidak akan memeriksa apa-apa tapi yangpublic_html
direktori untuk masing-masing pengguna.sumber
bash
shell Anda" ← dan globstar tidak diaktifkan.shopt -s globstar
dan coba lagi ...set -x
yang akan mulai mencetak perintah "aktual" yang dijalankan setiap kali (matikan bersamaset +x
).Dalam beberapa shell, termasuk bash 4.x dengan
globstar
opsi yang diaktifkan,**
akan melakukan gumpalan rekursif, menurun direktori yang cocok. Tanda bintang tambahan tidak mengubah operasi ini lebih jauh.sumber
ksh93
danzsh
,bash
apakah melintasi symlinks pada rekursi yang umumnya tidak diinginkan.Jika Anda ingin "menyelam lebih dalam", gunakan opsi ls -R (rekursif), atau gunakan find, seperti:
"find" akan turun ke bagian bawah pohon direktori (seperti akan 'ls -R'), dan memiliki banyak opsi lain, seperti daftar direktori (-type d), hanya file (-type f) atau menunjukkan file memiliki karakteristik (tidak ada pengguna di / etc / passwd, izin khusus, dan banyak lagi lainnya). "find" juga agak lebih aman dalam skrip (karena aturan globbing yang tidak konsisten antara shell, serta pelarian khusus untuk file yang memiliki garis putus-putus, dll).
shell wildcard globbing tidak akan bekerja hanya dengan tanda bintang '*' di file dot. Untuk daftar dotfiles saja, gunakan:
ls .??*
sumber
Ekstra * tidak menambah level kedalaman. Tetapi jika Anda mencoba
- Anda akan mendapatkan daftar subfolder subfolder di folder di folder saat ini ...
sumber
*
s tambahan akan menambah level kedalaman.bash
dengan opsi globstar, korn shell dan zsh. Dan mungkin yang lain, kurasa. unix.stackexchange.com/a/62665/14831Cengkeraman utama saya adalah gema ** / *. Ext umumnya akan ...
Mungkin atau Mungkin tidak: daftar file .ext di direktori saat ini
Mungkin atau Mungkin tidak: sertakan. *. Ext file
Secara umum saya lebih suka ekspresi glob menjadi '** /' dan yang dapat menghasilkan string nol (tidak ada sub-direktori). Inilah cara saya mengonversi ekspresi glob dalam input program. Tentu saja saya memastikan ada komentar yang menjelaskan hal ini dalam contoh penggunaan.
sumber