Wynik ls *, ls ** i ls ***


86

Wiem, że użycie polecenia lsspowoduje wyświetlenie listy wszystkich katalogów. Ale co robi ls *polecenie? Użyłem go i po prostu wyświetla katalogi. Czy gwiazda przed nim lsoznacza, jak głęboko może wyświetlić katalogi?

Odpowiedzi:


155

lswyświetla pliki i zawartość katalogów, które są przekazywane jako argumenty, a jeśli nie podano żadnego argumentu, wyświetla bieżący katalog. Można również przekazać szereg opcji, które wpływają na jego zachowanie (zobacz man lsszczegóły).

Jeśli lsprzekazywany jest argument o nazwie *, szuka pliku lub katalogu wywoływanego *w bieżącym katalogu i wyświetla go tak jak każdy inny. lsnie traktuje *postaci w żaden inny sposób niż jakikolwiek inny.

Jeśli jednak ls *jest wierszem poleceń powłoki , wówczas powłoka rozwinie ją *zgodnie z regułami globowania odpowiedniej powłoki ( zwanymi także Generowaniem nazwy pliku lub Rozszerzaniem nazwy pliku ).

Podczas gdy różne powłoki obsługują różne operatory globowania, większość z nich zgadza się na najprostszy *. *wzorzec oznacza dowolną liczbę znaków, więc *jako globrozwinięty zostanie lista plików w bieżących katalogach, które pasują do tego wzorca. Istnieje jednak wyjątek, że wiodący znak kropki ( .) w nazwie pliku musi być jawnie dopasowany, więc w *rzeczywistości rozwija się do listy plików i katalogów, które nie zaczynają się .(w kolejności leksykograficznej).

Na przykład, jeśli bieżący katalog zawiera pliki o nazwie ., .., .foo, -li foo bar, *zostanie rozszerzony przez powłokę do dwóch argumentów, aby przejść do ls: -li foo bartak będzie tak jakbyś wpisał:

ls -l "foo bar"

lub

'ls' "-l" foo\ bar

Jakie są trzy sposoby uruchomienia dokładnie tego samego polecenia. We wszystkich 3 przypadkach do lspolecenia (które prawdopodobnie zostanie wykonane z /bin/lswyszukiwania katalogów wymienionych w $PATH) zostaną przekazane te 3 argumenty: „ls”, „-l” i „foo bar”.

Nawiasem mówiąc, w tym przypadku lspierwszy (ściśle mówiąc drugi ) traktuje jako opcję.

Teraz, jak powiedziałem, różne powłoki mają różnych operatorów globowania. Kilka dekad temu zshwprowadzono **/operator¹, co oznacza dopasowanie do dowolnego poziomu podkatalogów, skrót (*/)#i ***/który jest taki sam, z tym wyjątkiem, że podąża za dowiązaniami symbolicznymi podczas zejścia do katalogów.

Kilka lat temu (lipiec 2003 r. ksh93o+) ksh93Postanowił skopiować to zachowanie, ale postanowił, że będzie to opcjonalne i objął tylko **sprawę (nie ***). Ponadto, chociaż **sam nie był wyjątkowy zsh(po prostu oznaczał to samo, co *w innych tradycyjnych powłokach, ponieważ **oznacza dowolną liczbę znaków, po której następuje dowolna liczba znaków), w ksh93 **oznaczał to samo co **/*(tak więc każdy plik lub katalog poniżej bieżącego) (z wyłączeniem ukrytych plików).

bashkopiowane ksh93kilka lat później (luty 2009, bash 4,0), z taką samą składnię, ale nieszczęśliwego różnicą: bash na **to jak zsh„s ***, że jest ono następujące dowiązania gdy recursing do podkatalogów, które generalnie nie jest to, co chcesz zrobić i może mieć nieprzyjemne skutki uboczne. Zostało to częściowo naprawione w bash-4.3, ponieważ dowiązania symboliczne były nadal śledzone, ale rekursja tam się zatrzymała. Zostało to w pełni naprawione w 5.0.

yashdodane **w wersji 2.0 w 2008 roku, włączone z extended-globopcją. Jego implementacja jest bliższa, zshponieważ **sam nie jest wyjątkowy. W wersji 2.15 (2009) dodawano, ***jak w, zshi dwa własne rozszerzenia: .**a także w .***celu uwzględnienia ukrytych katalogów podczas rekurencji (w zsh, D kwalifikator glob (jak w **/*(D)) będzie uwzględniał ukryte pliki i katalogi, ale jeśli chcesz tylko przechodzić ukryte katalogi, ale nie rozwijaj ukrytych plików, potrzebujesz ((*|.*)/)#*lub **/[^.]*(D)).

Skorupiaki obsługuje również **. Podobnie jak wcześniejsza wersja bash, po zejściu z drzewa katalogów podąża za dowiązaniami symbolicznymi. W tej powłoce nie **/*jest jednak taki sam jak **. **jest bardziej rozszerzeniem tego, *które może obejmować kilka katalogów. W fish, **/*.cbędzie pasował a/b/c.c, ale nie a.c, gdy a**.cbędzie pasował a.ci ab/c/d.ca zsh„s **/.*na przykład musi być napisane .* **/.*. Jest ***rozumiany jako **następujący po nim *tak samo jak **.

tcshdodano również globstaropcję w wersji 6.11 (maj 2010) i obsługuje zarówno **i ***à la zsh.

Więc tcsh, bashi ksh93(gdy odpowiednia opcja jest włączona ( globstar)) lub fish, **rozszerza wszystkich plików i katalogów poniżej obecnego, i ***jest taka sama jak **dla fish, miejsce linku przechodzącego **do tcshz globstar, i tak samo jak *w bashi ksh93(choć to nie jest niemożliwe, że przyszłe wersje tych powłok będą również przechodzić przez dowiązania symboliczne).

Powyżej zauważyłeś potrzebę upewnienia się, że żadne z rozszerzeń nie jest interpretowane jako opcja. W tym celu zrobiłbyś:

ls -- *

Lub:

ls ./*

Istnieje kilka poleceń (nie ma znaczenia ls), w których druga opcja jest lepsza, ponieważ nawet --niektóre nazwy plików mogą być traktowane specjalnie. To sprawa -dla większości narzędzi tekstowych, cda pushdi nazwy plików, które zawierają =znak dla awkna przykład. Przechodzenie ./do wszystkich argumentów usuwa ich specjalne znaczenie (przynajmniej w przypadkach wspomnianych powyżej).

Należy również zauważyć, że większość powłok ma wiele opcji, które wpływają na zachowanie globowania (np. Czy pliki kropek są ignorowane, czy nie, kolejność sortowania, co zrobić, jeśli nie ma dopasowania ...), patrz również $FIGNOREparametr wksh

Ponadto, w każdej muszli ale csh, tcsh, fishi zsh, jeżeli wzór globbing nie pasuje do żadnego pliku, wzór jest przekazywana jako nierozszerzonym argument, który powoduje zamieszanie i ewentualnie błędy. Na przykład, jeśli w bieżącym katalogu nie ma nie ukrytego pliku

ls *

Zadzwoni lsz dwoma argumentami lsi *. A ponieważ nie ma w ogóle żadnego pliku, więc żaden z nich nie jest wywoływany *, zobaczysz komunikat o błędzie z ls (nie z powłoki), taki jak:, o ls: cannot access *: No such file or directoryktórym wiadomo, że ludzie myślą, lsże to właśnie rozszerzał globusy.

Problem jest jeszcze gorszy w przypadkach takich jak:

rm -- *.[ab]

Jeśli nie ma *.aani *.bpliku w bieżącym katalogu, to może skończyć się usunięciem pliku o nazwie *.[ab]przez pomyłkę ( csh, tcsh, i zshby zgłosić Brak odpowiednika błąd i nie zadzwonić rm(i fishnie obsługuje [...]symboli wieloznacznych)).

Jeśli chcesz przekazać dosłownym *się ls, trzeba zacytować tę *postać w jakiś sposób, w ls \*lub ls '*'lub ls "*". W powłokach podobnych do POSIX, globbing można całkowicie wyłączyć za pomocą set -o nogloblub set -f(ten ostatni nie działa, zshchyba że w sh/ kshemulacji).


¹ Chociaż (*/)#zawsze był obsługiwany, najpierw był krótkotrwały, jak ..../w Zsh-2.0 (i potencjalnie wcześniej), a następnie ****/w 2.1, zanim uzyskał ostateczną formę **/w 2.2 (początek 1992 r.)


22
Naprawdę świetna odpowiedź!
Andrea Corbellini,

7
Innym dobrym przykładem jest find -name *. Zwłaszcza w przypadku bardziej złożonych wzorców, jeśli w bieżącym katalogu jest dokładnie jedno dopasowanie, ludzie często nie zdają sobie sprawy, że nie przekazują gwiazdki find.
njsg

Nadal daję +1, bardzo się cieszę, że Stephane Chazelas jest aktywny tutaj na unix.stackexchange.com ! Świetny wkład, Stephane, jak zawsze!
Dimitre Radoulov

1
U ryb *.[ab]próbowałby usunąć wszystko, co kończy się na .[ab]. [nie jest wyjątkowy u ryb.
Konrad Borowski

35

lsDomyślnie polecenie to ls .: Wyświetl wszystkie wpisy w bieżącym katalogu .

Polecenie ls *oznacza „uruchom ls na rozwinięciu *wzorca powłoki”

*Wzorzec jest przetwarzany przez powłokę i rozwija się do wszystkich wpisów w bieżącym katalogu, z wyjątkiem tych, które zaczynają się .. Zejdzie o jeden poziom w głąb.

Interpretacja *wzorów podwójnych lub potrójnych zależy od rzeczywistej użytej powłoki.

*to symbol wieloznaczny, który pasuje do 0 lub więcej znaków. Niektóre nowoczesne powłoki powrócą do podkatalogów po zobaczeniu **wzorca.


17
Tyle tylko, że dodatkowo * zrobić coś dodać, zobaczyć inną odpowiedź wyjaśniającą globstar. Należy również wyjaśnić, że ls nie ma nic wspólnego z gwiazdkami, nigdy nie minęła żadnej z tych gwiazdek. Uruchom, echo ls *aby zobaczyć, co zostanie wykonane podczas pisania ls *.
njsg

12

Możesz zdemistyfikować cały proces, wpisując echozamiast lspierwszego, aby zobaczyć, do czego służy rozwinięcie polecenia:

$ echo *
Applications Downloads Documents tmp.html

W tym przypadku ls *rozwija się dols Applications Downloads Documents tmp.html

$ echo **
Applications Downloads Documents tmp.html

$ echo ***
Applications Downloads Documents tmp.html

Więc bez zmian. Zakłada się, że używasz bashjako powłoki - większość ludzi, a różne powłoki zachowują się inaczej. Jeśli używasz ashlub cshlub kshlub zsh, możesz oczekiwać, że wszystko będzie działać inaczej. Chodzi o to, żeby mieć różne muszle.

Spróbujmy więc czegoś innego (nadal z bash), abyśmy mogli dowiedzieć się, co *operator globbing ( ) może dla nas zrobić. Na przykład możemy filtrować według części nazwy:

$ echo D*
Downloads Documents

Co ciekawe, ukośnik końcowy jest domyślnie częścią każdej nazwy katalogu. Czyli */zwróci tylko katalogi (i dowiązania symboliczne do katalogów):

$ echo */
Applications/ Downloads/ Documents/

Możemy też przeprowadzić filtrowanie na wielu poziomach, umieszczając ukośniki na środku:

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

Ponieważ Downloadskatalog nie zawiera żadnych podkatalogów, nie kończy się w wyniku. Jest to bardzo przydatne do sprawdzania potrzebnych plików. Cały czas używam takich poleceń:

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

Zawiera listę, jeśli istnieją, wszystkich wp-config.phpplików, które istnieją na poziomie podstawowym public_htmlkatalogu dowolnego użytkownika . A może być bardziej kompletny:

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

W ten sposób znaleźliśmy żadnych wp-config.phpplików w dowolnym użytkownika public_htmlkatalogów lub którykolwiek z ich podkatalogów, ale będzie działać bardziej efektywnie niż po prostu find /home/ -name wp-config.phpdlatego, że nie będzie badać niczego , ale z public_htmlkatalogów dla każdego z użytkowników.


1
„Zakłada się, że używasz bashjako powłoki” ← i że globstar nie jest włączony. shopt -s globstari spróbuj ponownie ...
njsg

Innym sposobem na odtajnienie jest set -xrozpoczęcie drukowania „rzeczywistego” polecenia wykonywanego za każdym razem (wyłącz za pomocą set +x).
ShreevatsaR

10

W niektórych powłokach, w tym bash 4.x z globstarwłączoną opcją, **wykona rekurencyjne glob, malejące dopasowane katalogi. Dodatkowe gwiazdki nie modyfikują tej operacji.


1
Jednak, jak powiedziałem w mojej odpowiedzi, strzeżcie się, że w przeciwieństwie do ksh93i zsh, bashprzechodzą dowiązania symboliczne w rekurencji, co jest na ogół niepożądane.
Stéphane Chazelas

Zostało to teraz naprawione w bash 4.3
Stéphane Chazelas

1

Jeśli chcesz „zanurzyć się głęboko”, użyj opcji ls -R (rekurencyjnej) lub użyj find:

find . -ls

„find” zanurkuje w dół drzewa katalogów (podobnie jak „ls -R”) i ma wiele innych opcji, takich jak wyświetlanie katalogów (-type d), tylko plików (-type f) lub pokazywanie plików mających inne cechy (brak użytkownika w / etc / passwd, określone uprawnienia i wiele więcej). „find” jest również nieco bezpieczniejsze w skryptach (ze względu na niespójne reguły globowania między powłokami, a także specjalne zmiany znaczenia dla plików z myślnikami itp.).

globbing wieloznaczny powłoki nie będzie działał z gwiazdką „*” w plikach dot. Aby wyświetlić tylko listę plików kropkowych, użyj:

ls .??*


-1

Extra * nie dodaje poziomu głębi. Ale jeśli spróbujesz

 ls */*/*

- otrzymasz listę podfolderów podfolderów w folderach w bieżącym folderze ...


Źle. W zależności od powłoki dodatkowe *s zwiększą poziom głębokości.
njsg

więc jaka skorupa doda poziom głębi do dodatkowych gwiazd?
VB9-UANIC

Kilka. W tym GNU bashz opcją globstar, powłoką Korn i zsh. I prawdopodobnie inni, tak sądzę. unix.stackexchange.com/a/62665/14831
njsg

-1

Moim głównym chwytem jest to, że echo ** / *. Ext ogólnie ...

Może lub nie: lista plików .ext w bieżącym katalogu

Może lub nie może: dołączać pliki. *. Ext

Ogólnie wolałbym, aby wyrażenie glob było „** /” i które może skutkować ciągiem zerowym (brak podkatalogu). W ten sposób przekształcam wyrażenia globalne w danych wejściowych programu. Oczywiście upewniam się, że w przykładach użycia wyjaśniają to komentarze.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.