Wiem, że użycie polecenia ls
spowoduje 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 ls
oznacza, jak głęboko może wyświetlić katalogi?
ls
wyś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 ls
szczegóły).
Jeśli ls
przekazywany jest argument o nazwie *
, szuka pliku lub katalogu wywoływanego *
w bieżącym katalogu i wyświetla go tak jak każdy inny. ls
nie 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 glob
rozwinię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
, -l
i foo bar
, *
zostanie rozszerzony przez powłokę do dwóch argumentów, aby przejść do ls
: -l
i foo bar
tak 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 ls
polecenia (które prawdopodobnie zostanie wykonane z /bin/ls
wyszukiwania katalogów wymienionych w $PATH
) zostaną przekazane te 3 argumenty: „ls”, „-l” i „foo bar”.
Nawiasem mówiąc, w tym przypadku ls
pierwszy (ś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 zsh
wprowadzono **/
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+
) ksh93
Postanowił 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).
bash
kopiowane ksh93
kilka 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.
yash
dodane **
w wersji 2.0 w 2008 roku, włączone z extended-glob
opcją. Jego implementacja jest bliższa, zsh
ponieważ **
sam nie jest wyjątkowy. W wersji 2.15 (2009) dodawano, ***
jak w, zsh
i 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
, **/*.c
będzie pasował a/b/c.c
, ale nie a.c
, gdy a**.c
będzie pasował a.c
i ab/c/d.c
a zsh
„s **/.*
na przykład musi być napisane .* **/.*
. Jest ***
rozumiany jako **
następujący po nim *
tak samo jak **
.
tcsh
dodano również globstar
opcję w wersji 6.11 (maj 2010) i obsługuje zarówno **
i ***
à la zsh
.
Więc tcsh
, bash
i 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 tcsh
z globstar
, i tak samo jak *
w bash
i 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, cd
a pushd
i nazwy plików, które zawierają =
znak dla awk
na 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ż $FIGNORE
parametr wksh
Ponadto, w każdej muszli ale csh
, tcsh
, fish
i 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 ls
z dwoma argumentami ls
i *
. 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 directory
któ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 *.a
ani *.b
pliku w bieżącym katalogu, to może skończyć się usunięciem pliku o nazwie *.[ab]
przez pomyłkę ( csh
, tcsh
, i zsh
by zgłosić Brak odpowiednika błąd i nie zadzwonić rm
(i fish
nie 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 noglob
lub set -f
(ten ostatni nie działa, zsh
chyba że w sh
/ ksh
emulacji).
¹ 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.)
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ą gwiazdkifind
.*.[ab]
próbowałby usunąć wszystko, co kończy się na.[ab]
.[
nie jest wyjątkowy u ryb.ls
Domyślnie polecenie tols .
: 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.źródło
*
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 pisanials *
.Możesz zdemistyfikować cały proces, wpisując
echo
zamiastls
pierwszego, aby zobaczyć, do czego służy rozwinięcie polecenia:W tym przypadku
ls *
rozwija się dols Applications Downloads Documents tmp.html
Więc bez zmian. Zakłada się, że używasz
bash
jako powłoki - większość ludzi, a różne powłoki zachowują się inaczej. Jeśli używaszash
lubcsh
lubksh
lubzsh
, 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: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):Możemy też przeprowadzić filtrowanie na wielu poziomach, umieszczając ukośniki na środku:
Ponieważ
Downloads
katalog 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ń:Zawiera listę, jeśli istnieją, wszystkich
wp-config.php
plików, które istnieją na poziomie podstawowympublic_html
katalogu dowolnego użytkownika . A może być bardziej kompletny:W ten sposób znaleźliśmy żadnych
wp-config.php
plików w dowolnym użytkownikapublic_html
katalogów lub którykolwiek z ich podkatalogów, ale będzie działać bardziej efektywnie niż po prostufind /home/ -name wp-config.php
dlatego, że nie będzie badać niczego , ale zpublic_html
katalogów dla każdego z użytkowników.źródło
bash
jako powłoki” ← i że globstar nie jest włączony.shopt -s globstar
i spróbuj ponownie ...set -x
rozpoczęcie drukowania „rzeczywistego” polecenia wykonywanego za każdym razem (wyłącz za pomocąset +x
).W niektórych powłokach, w tym bash 4.x z
globstar
włączoną opcją,**
wykona rekurencyjne glob, malejące dopasowane katalogi. Dodatkowe gwiazdki nie modyfikują tej operacji.źródło
ksh93
izsh
,bash
przechodzą dowiązania symboliczne w rekurencji, co jest na ogół niepożądane.Jeśli chcesz „zanurzyć się głęboko”, użyj opcji ls -R (rekurencyjnej) lub użyj find:
„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 .??*
źródło
Extra * nie dodaje poziomu głębi. Ale jeśli spróbujesz
- otrzymasz listę podfolderów podfolderów w folderach w bieżącym folderze ...
źródło
*
s zwiększą poziom głębokości.bash
z opcją globstar, powłoką Korn i zsh. I prawdopodobnie inni, tak sądzę. unix.stackexchange.com/a/62665/14831Moim 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.
źródło