Ls *, ls ** ve ls ***'nin sonucu


86

Komutu kullanmanın lstüm dizinleri listeleyeceğini biliyorum . Fakat ls *emir ne yapar ? Kullandım ve sadece dizinleri listeler. Önündeki yıldız ls, dizinleri listeleme derinliği anlamına mı geliyor?

Yanıtlar:


155

lsArgüman olarak iletilen dizinlerin dosyalarını ve içeriğini listeler ve argüman verilmezse, geçerli dizini listeler. Davranışını etkileyen bir dizi seçenek de geçebilir ( man lsayrıntılar için bakınız).

Eğer lsadlandırılan bir argüman geçirildiği için *, adı bir dosya veya dizini arar *geçerli dizinde ve sadece diğerleri gibi sıralar. karaktere, diğerinden daha farklı şekilde lsdavranmaz *.

Bununla birlikte ls *, bir kabuk komut satırı ise, kabuk *karşılık gelen kabuğun toparlanmasına ( Dosya Adı Oluşturma veya Dosya Adı Genişletme olarak da bilinir ) kurallarına göre genişler .

Farklı mermiler farklı globbing operatörlerini desteklerken, çoğu en basit olanı üzerinde anlaşır *. *Bir model *olarak glob, geçerli dizinlerdeki o modelle eşleşen dosyaların listesine genişleyeceği şekilde herhangi bir sayıda karakter anlamına gelir . Bununla birlikte, bir .dosya adındaki baş nokta ( ) karakterinin açıkça eşleştirilmesi gerektiğinin bir istisnası vardır, bu nedenle *aslında .(sözlüksel sırayla) başlamamış dosya ve dizin listesine genişler .

Geçerli dizin adı verilen dosyaları içeren Örneğin, eğer ., .., .foo, -lve foo bar, *geçmek iki argümanları kabuk tarafından genişletilecek ls: -lve foo baro yazdığınız sanki olacak, böylece:

ls -l "foo bar"

veya

'ls' "-l" foo\ bar

Tamamen aynı komutu çalıştırmak için üç yol. Her 3 durumda da, lskomut (muhtemelen içinde /bin/lsbelirtilen dizinlerin aranmasından itibaren yürütülecektir $PATH) şu 3 argümandan geçecektir: "ls", "-l" ve "foo bar".

Bu arada, bu durumda, lsilk (kesinlikle ikinci konuşan ) birini bir seçenek olarak ele alacağım .

Şimdi dediğim gibi, farklı mermilerin farklı globbing operatörleri var. Birkaç yıl önce, zshtanıtılan **/kısaca, alt dizinleri herhangi bir düzeyde maç için anlamı operator¹ (*/)#ve ***/dizinleri inen ederken sembolik bağları takip haricinde aynı olan.

Birkaç yıl önce (Temmuz 2003, ksh93o+), ksh93bu davranışı kopyalamaya karar verdi, ancak isteğe bağlı hale getirmeye karar verdi ve yalnızca durumu ele aldı **(değil ***). Ayrıca, **tek başına özel değildi zsh(sadece *diğer geleneksel kabuklarda olduğu gibi aynı **anlama geldiğinden, herhangi bir sayıda karakterin ardından gelen herhangi bir sayıda karakter anlamına gelir), ksh93'de, (geçerli dosyanın altındaki herhangi bir dosya veya dizinin **aynısı) **/*(gizli dosyalar hariç).

bashKopyalanan ksh93birkaç yıl sonra (Şubat 2009, bash 4.0) aynı sözdizimi ama talihsiz bir farkla: bash en **gibiydi zsh's ***alt dizinleri içine recursing zaman bunu yapmak istediğini genelde olmadığı sembolik takip ediyordu, yani ve kötü yan etkileri olabilir. Kısım 4.3'te, semboliklerin hala takip edildiği, ancak özyineleme orada durduğu için kısmen düzeltildi. 5.0'da tamamen sabitlendi.

yashseçeneği **ile etkinleştirilmiş, 2008 yılında 2.0 sürümünde eklendi extended-glob. Uygulanmasına daha yakın zsholduğu için **tek başına özel değildir. 2.15 (2009) sürümünde , kendi uzantılarının ***içindekiler zshve ikisi gibi eklenmiştir : .**ve .***yinelemede gizli dizinler eklemek (içeride zsh, D glob niteleyicisi ( içeride olduğu gibi **/*(D)) gizli dosyaları ve dizinleri göz önünde bulundurur, ancak yalnızca gizli öğeleri geçmek istiyorsanız dirs ancak gizli dosyaları genişletmeyin, ihtiyacınız olan ((*|.*)/)#*veya **/[^.]*(D)).

Balık kabuk da destekler **. Daha önceki sürümlerde olduğu gibi bashdizin ağacını inerken sembolik izleri izler. Ancak bu kabukta **/*aynı değildir **. **bunun bir uzantısı *birkaç dizine yayılabilir. Olarak fish, **/*.cmaç olacak a/b/c.cancak a.cederken, a**.cmaç olacak a.cve ab/c/d.cve zsh'nin **/.*örneğin yazılacak vardır .* **/.*. Burada, ***olarak anlaşılmalıdır **ardından *şekilde aynı **.

tcshAyrıca eklenen globstarV6.17.01 (2010 Mayıs) seçeneği ve destekler **ve ***la à zsh.

Yani içinde tcsh, bashve ksh93, (ilgili seçeneği etkinleştirildiğinde ( globstar)) ya da fish, **mevcut olanın altına tüm dosyaları ve dizinleri genişler ve ***aynıdır **için fishkateden bir sembolik bağ, **için tcshbirlikte globstarve aynı *içinde bashve ksh93bu kadar olsa ( Bu mermilerin gelecekteki versiyonlarının da sembolik bağlantıları geçmesi imkansız değil).

Yukarıda, genişletmelerin hiçbirinin bir seçenek olarak yorumlanmadığından emin olma gereğini fark ettiniz. Bunun için yapardın:

ls -- *

Veya:

ls ./*

Bazı dosya isimleriyle lsbile --özel olarak ele alınabildiğinden ikincinin tercih edilebileceği bazı komutlar vardır (önemli değil ) . Bu -, çoğu metin yardımcı programında cdve örneğin karakterini pushdiçeren dosya adlarında geçerlidir . Tüm argümanlara hazırlık yapmak, özel anlamlarını kaldırır (en azından yukarıda belirtilen durumlar için).=awk./

Aynı zamanda en kabukları ayrıca bkz, (herhangi bir eşleşme varsa ne yapacağını, sıralama düzeni nokta dosyaları göz ardı edilip gibi ya da değil, ...) globbing davranışını etkileyen çeşitli seçenekler var olduğunu belirtmek gerekir $FIGNOREparametre içindeksh

Ayrıca, her kabukta ama csh, tcsh, fishve zsheğer globbing desen herhangi bir dosyayı uymuyor, desen karışıklık ve muhtemelen böcek neden olan bir genişlememe argüman olarak geçirilir. Örneğin, geçerli dizinde gizli olmayan bir dosya yoksa

ls *

Aslında lsiki argüman ile arayacak lsve *. Ve hiçbir dosya olmadığı için, hiçbiri de çağrılmadı *, ls'den (kabuk değil) gelen bir hata mesajı göreceksiniz : ls: cannot access *: No such file or directoryki bu, insanların lsaslında bunun dünyayı genişlettiğini düşünmesini sağladı .

Sorun, aşağıdaki gibi durumlarda daha da kötüdür:

rm -- *.[ab]

Hiçbir varsa *.ane de *.bgeçerli dizinde dosyayı, o zaman adlı bir dosya silme sonunda olabilir *.[ab]yanlışlıkla ( csh, tcshve zshbir rapor verecek hiçbir eşleşme hatası ve demezdim rm(ve fishdesteklemez [...]joker)).

Eğer bir değişmez geçirmek istediğiniz yoksa *üzere ls, bunu belirtmek zorunda *olduğu gibi bir şekilde karakterini ls \*veya ls '*'veya ls "*". POSIX benzeri mermilerde globbing tamamen set -o noglobveya kullanılarak set -f( devre dışı bırakılmadıkça / zshçalışmaz ) çalışmaz .shksh


Always Her (*/)#zaman desteklenirken ilk önce ..../zsh-2.0'da (ve potansiyel olarak önce) olduğu gibi kısa yoldan, daha sonra ****/da 2.1'de **/(1992 başlarında) kesin biçimini almadan önce 2.1 olarak verildi.


22
Gerçekten harika cevap!
Andrea Corbellini

7
Bir başka güzel örnek find -name *. Özellikle daha karmaşık modellerle, geçerli dizinde tam olarak bir eşleşme olursa, insanlar genellikle yıldız işaretini geçmediklerini farketmeyeceklerdir find.
njsg

Ben burada Stephane Chazelas aktif görmek gerçekten çok mutluyum, +1 vermeye devam unix.stackexchange.com ! Harika katkılar, Stephane, her zamanki gibi!
Dimitre Radoulov

1
Balıkta, *.[ab]biten her şeyi silmeye çalışırdım .[ab]. [balıklarda özel değildir.
Konrad Borowski

35

Komut lsvarsayılan olarak ls .: Geçerli dizindeki tüm girişleri listeler .

Komut ls *' *Kabuk düzeninin genişlemesinde ls çalıştır' anlamına gelir.

*Desen kabuk tarafından işlenir ve bir ile başlayan olanlar hariç olmak üzere, geçerli dizindeki tüm girişlere genleşir .. Bir seviye derin gidecek.

İkili veya üçlü *modellerin yorumlanması, kullanılan gerçek kabuğa bağlıdır.

*0 veya daha fazla karakterle eşleşen bir joker karakterdir. Bazı modern kabukları, **deseni görünce alt dizinlere taşınır .


17
Bu fazladan bir * şey eklemek dışında , globtarı açıklayan diğer cevaba bakınız. Ayrıca , yıldızlarla hiçbir ilgisi olmadığı, bu yıldızlardan hiçbiri geçmediği açıkça belirtilmelidir . Yazarken echo ls *ne yürütüleceğini görmek için koş ls *.
njsg

12

Komutun neye genişlediğini görmek için önce echoyerine yazarak işlemin tamamını silinebilirsiniz ls:

$ echo *
Applications Downloads Documents tmp.html

Yani bu durumda, ls *genişlerls Applications Downloads Documents tmp.html

$ echo **
Applications Downloads Documents tmp.html

$ echo ***
Applications Downloads Documents tmp.html

Yani değişiklik yok. Bu bash, kabuğunuz olarak kullandığınızı varsayar - çoğu insan ve farklı mermilerin farklı davranışları vardır. Kullanıyorsanız ashveya cshveya kshveya kullanıyorsanız zsh, işlerin farklı şekilde çalışmasını bekleyebilirsiniz. Farklı mermilere sahip olmanın amacı budur.

Öyleyse farklı bir şeyi deneyelim (hala ile bash), böylece globbing ( *) operatörünün bizim için yapabileceği hakkında bir fikir edinebiliriz . Örneğin, adın bir bölümüne göre filtreleyebiliriz:

$ echo D*
Downloads Documents

Ve ilginç bir şekilde, sondaki eğik çizgi, herhangi bir dizin adının örtük olarak bir parçasıdır. Dolayısıyla */, yalnızca dizinleri (ve dizinlere sembolik linkleri) verir:

$ echo */
Applications/ Downloads/ Documents/

Ve ortada eğik çizgiler koyarak birkaç düzeyde bazı filtreler yapabiliriz:

$ echo D*/*/
Documents/Work/ /Documents/unfinished/

Yana Downloadsdizin tüm alt içermez, bu çıktıda kadar bitmez. Bu sadece istediğiniz dosyaları incelemek için çok kullanışlıdır. Bu gibi komutları her zaman kullanırım:

$ ls -l /home/*/public_html/wp-config.php

Bu, varsa, herhangi wp-config.phpbir kullanıcının public_htmldizininin temel düzeyinde bulunan tüm dosyaları listeler . Ya da belki daha eksiksiz olmak için:

$ find /home/*/public_html/ -name wp-config.php

Bu, herhangi bulacaksınız wp-config.phpherhangi bir kullanıcının dosyaları public_htmldizinleri veya bunların alt dizinleri herhangi fakat daha verimli sadece daha çalışacaktır find /home/ -name wp-config.phpbir şey incelemek çünkü ancakpublic_html kullanıcıların her biri için dizinleri.


1
"Bu bash, kabuğunuz olarak kullandığınızı varsayar " ← ve globstar'ın etkin olmadığını. shopt -s globstarve tekrar deneyin ...
njsg

Gösterimin set -xkaldırılmasının bir başka yolu da, her seferinde yürütülen "gerçek" komutunu basmaya başlamasıdır (kapat set +x).
ShreevatsaR

10

globstarSeçeneği etkinleştirilmiş bash 4.x dahil olmak üzere bazı kabuklarda, **eşleşen dizinleri azalan özyinelemeli bir glob gerçekleştirir. Ek yıldız işaretleri bu işlemi daha fazla değiştirmez.


1
Gerçi benim cevap söylediği gibi, bu aykırı dikkat ksh93ve zsh, bashgenellikle istenmeyen olduğu özyinelemede travers sembolik yapar.
Stéphane Chazelas

Bu şimdi bash 4.3'te düzeltildi
Stéphane Chazelas

1

Eğer "derinlere dalmak" istiyorsanız, ls -R (özyinelemeli) seçeneğini kullanın veya şunun gibi bul:

find . -ls

"find", dizin ağacının altına ('ls -R' de olduğu gibi) dalacak ve dizinleri (-type d) listeleme, sadece dosyaları (-type f) ya da diğer dosyaları gösterme gibi daha birçok seçeneğe sahip olacak özellikleri (/ etc / passwd'de kullanıcı yok, belirli izinler ve daha fazlası). "find" komut dosyası için de biraz daha güvenlidir (mermiler arasındaki tutarsız globbing kurallarının yanı sıra, kısa çizgi içeren dosyalar için özel çıkışlar vb.).

shell joker globbing, dotfiles üzerinde sadece '*' yıldız işaretiyle çalışmaz. Yalnızca nokta dosyalarını listelemek için şunu kullanın:

ls .??*


-1

Ekstra * derinlik seviyesi eklemiyor. Ama denersen

 ls */*/*

- Geçerli klasördeki klasörlerdeki alt klasörlerin listesini alırsınız ...


Yanlış. Kabuğa bağlı olarak, ekstra *s derinlik seviyesi ekleyecektir.
njsg

Peki hangi kabuk fazladan yıldızlara derinlik katar?
VB9-UANIC,

Birkaç. bashGlobstar seçeneği ile GNU dahil , korn shell ve zsh. Ve muhtemelen diğerleri, sanırım. unix.stackexchange.com/a/62665/14831
njsg

-1

Benim ana kavrama yankı ** / *. Ext genellikle ...

Mayıs ya da Mayıs: geçerli dizinde bir .ext dosyasını listeleyebilir

Mayıs veya Mayıs değil: içer. *. Ext dosyaları

Genelde, glob ifadesinin '** /' olmasını ve boş bir dizeyle sonuçlanabileceğini (alt dizin yok) tercih ederim. Bu, program girişindeki glob ifadelerini böyle dönüştürür. Tabii ki bunu kullanım örneklerinde açıklayan yorumlar olduğunu garanti ediyorum.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.