dlaczego ls -d także wyświetla listę plików i gdzie jest to udokumentowane?


48
  • podczas określania ls --directory a*należy wymienić tylko katalogi zaczynające się oda*
  • ALE wyświetla listę plików i katalogów zaczynających się od a

Pytania :

  • gdzie mogę znaleźć dokumentację na ten temat, poza tym mani infogdzie, jak sądzę, dokładnie się przyjrzałem?
  • czy to działa tylko w BASH?


5
echo a*wyświetli również listę plików zaczynających się od a(jeśli istnieją). Żeby było bardziej jasne, że to nie lsrobi tego, ale bash.
ash108

Odpowiedzi:


89

a*I *a*składnia jest realizowany przez powłokę, a nie przez lskomendę.

Kiedy piszesz

ls a*

po zachęcie powłoki powłoka rozwija się a*do listy istniejących wszystkich plików w bieżącym katalogu, których nazwy zaczynają się a. Na przykład może rozwinąć a*się do sekwencji a1 a2 a3i przekazać je jako argumenty do ls. Samo lspolecenie nigdy nie widzi *postaci; to widzi tylko trzy argumenty a1, a2i a3.

Do celów interpretacji symboli wieloznacznych „pliki” odnoszą się do wszystkich jednostek w bieżącym katalogu. Na przykład a1może być normalnym plikiem, a2może być katalogiem i a3może być dowiązaniem symbolicznym. Wszystkie mają wpisy w katalogu, a rozszerzenie symboli wieloznacznych powłoki nie ma znaczenia, do jakiego rodzaju encji odnoszą się te wpisy.

Praktycznie wszystkie powłoki, na które prawdopodobnie natkniesz się (bash, sh, ksh, zsh, csh, tcsh, ...) implementują symbole wieloznaczne. Szczegóły mogą się różnić, ale podstawowa składnia *dopasowywania zera lub więcej znaków i ?dopasowywania dowolnego pojedynczego znaku jest dość spójna.

W szczególności w przypadku bash jest to udokumentowane w sekcji „Rozszerzenie nazwy pliku” podręcznika bash; uruchom info bashi wyszukaj „Rozszerzenie nazwy pliku” lub zobacz tutaj .

Fakt, że robi to powłoka, a nie poszczególne polecenia, ma pewne interesujące (i czasem zaskakujące) konsekwencje. Najlepsze w tym jest to, że obsługa symboli wieloznacznych jest spójna dla (bardzo) wszystkich poleceń; jeśli powłoka tego nie zrobi, nieuchronnie niektóre polecenia nie zawracałyby sobie głowy, a inne robiłyby to w nieco inny sposób, który autor uważał za „lepszy”. (Myślę, że powłoka poleceń systemu Windows ma ten problem, ale nie znam go wystarczająco dobrze, aby komentować dalej.)

Z drugiej strony trudno jest napisać polecenie zmiany nazwy wielu plików. Jeśli napiszesz:

mv *.log *.log.bak

prawdopodobnie zawiedzie, ponieważ *.log.bakjest rozwijany na podstawie plików, które już istnieją w bieżącym katalogu. Istnieją polecenia, które robią takie rzeczy, ale muszą używać własnej składni, aby określić sposób zmiany nazwy plików. Niektóre polecenia (takie jak find) mogą wykonywać własne interpretacje symboli wieloznacznych; musisz zacytować argumenty, aby stłumić rozszerzenie powłoki:

find . -name '*.txt' -print

Rozszerzenie symboli wieloznacznych powłoki jest całkowicie oparte na składni argumentu wiersza poleceń i zestawie istniejących plików. To nie może być dotknięte rozumieniu polecenia. Na przykład, jeśli chcesz przenieść wszystkie .logpliki do katalogu nadrzędnego, możesz wpisać:

mv *.log ..

Jeśli zapomnisz ..:

mv *.log

a akurat .logw katalogu bieżącym znajdują się dokładnie dwa pliki, rozwinie się do:

mv one.log two.log

który zmieni nazwę one.logi zablokuje two.log.

EDYCJA : A po 52 opiniach, akceptacji i odznace Guru, może powinienem właściwie odpowiedzieć na pytanie w tytule.

-dLub --directoryopcja lsnie powiedzieć go do listy tylko katalogów. Mówi o tym, żeby wyświetlała katalogi tak jak one same, a nie ich zawartość. Jeśli podasz nazwę katalogu jako argument ls, domyślnie wyświetli ona zawartość katalogu, ponieważ zwykle jest to tym, co cię interesuje. -dOpcja ta nakazuje mu wyświetlić tylko sam katalog. Może to być szczególnie przydatne w połączeniu z symbolami wieloznacznymi. Jeśli wpiszesz:

ls -l a*

lspoda długą listę każdego pliku, którego nazwa zaczyna się od a, oraz zawartości każdego katalogu, którego nazwa zaczyna się od a. Jeśli chcesz tylko listę plików i katalogów, po jednej linii dla każdego, możesz użyć:

ls -ld a*

co jest równoważne z:

ls -l -d a*

Pamiętaj jeszcze raz, że lspolecenie nigdy nie widzi *postaci.

Jeśli chodzi o to, gdzie jest to udokumentowane, man lspokaże ci dokumentację lspolecenia na prawie każdym systemie uniksopodobnym. W większości systemów opartych na Linuxie lspolecenie jest częścią pakietu GNU coreutils; jeśli masz infopolecenie, albo powinien info lslub info coreutils lspowinien dać ci bardziej ostateczną i wyczerpującą dokumentację. Inne systemy, takie jak MacOS, mogą używać różnych wersji lspolecenia i mogą nie mieć infopolecenia; dla tych systemów użyj man ls. I ls --helppokaże stosunkowo krótki komunikat o użyciu (117 linii w moim systemie), jeśli używasz implementacji GNU coreutils.

I tak, nawet eksperci muszą od czasu do czasu sprawdzać dokumentację. Zobacz także ten klasyczny żart .


8
@ Thomas: a*rozwija się do listy wszystkich plików w bieżącym katalogu, których nazwy zaczynają się a.
Keith Thompson,

2
@ Thomas: Lub w dowolnym katalogu, który określisz:ls subdir/a*
Keith Thompson

1
Aby naprawdę zobaczyć polecenie wykonane po rozszerzeniu powłoki, echoto. Jeśli więc chcesz wiedzieć, co się dzieje, wykonaj ls a*najpierwecho ls a*
Carlos Campderrós

1
lub po prostu echo a*... powłoka i tak dokonuje globalnej ekspansji
Bezużyteczne

2
@sendmoreinfo: To zależy od powłoki i ustawień. W csh i tcsh błąd globalnego rozszerzenia jest błędem. W bash shopt -s failglobpowoduje to samo zachowanie. Ustawienie, nullglobale nie failglobpowoduje, na przykład *nosuchfile*rozwinięcia do pustego ciągu.
Keith Thompson

27

Zobacz odpowiedź Keitha Thompsona; ale aby wyjaśnić, dlaczego ls --directory a*wyświetla pliki i katalogi: Ta --directoryopcja nie pomija plików spoza katalogu. Zamiast tego wyświetla katalogi jako takie, podczas gdy w przeciwnym razie wyświetlałoby ich zawartość. Przykład:

$ mkdir foo
$ touch foo/bar
$ ls foo
bar
$ ls --directory foo
foo

3
ten przykład jest bardziej przekonujący z -Fopcją
glenn jackman

6

Mówiąc wprost, jest to udokumentowane na stronie podręcznika ls (1) :

-d, --directory wyświetla pozycje katalogu zamiast zawartości i nie wyklucza dowiązań symbolicznych

szczerze mówiąc, „wpisy zamiast treści” mogłyby być bardziej objaśniające:

Jeśli PLIK jest katalogiem, pokaż sam wpis katalogu zamiast wyświetlać zawartość tego katalogu. Jeśli PLIK jest dowiązaniem symbolicznym, pokaż sam wpis dowiązania zamiast pliku wskazanego przez dowiązanie.


Aby być pedantycznym, podczas gdy opcja -d może być wyjaśniona (jeśli zwięźle) na stronie man, interpretacja argumentów i symbole wieloznaczne nie są dokumentowane na stronie man ls, ponieważ jest to wykonywane przez powłokę. Jeśli wyłączyłeś rozszerzanie nazw plików w swojej powłoce, „ls a *” pokaże tylko plik, który dosłownie nazywa się „a *”.
Johnny

Mówiąc pedantycznie, podczas gdy inni respondenci odpowiedzieli na ekspansję powłoki, żaden z nich nie odnosi się do skąpych wyjaśnień i tego, jak można je źle odczytać. Jeśli chcesz, abym powtórzył to, co już zostało dobrze powiedziane, proszę, bądź bardziej bezpośredni.
msw

4

Globbing

Jak wyjaśniono, rozszerzenie *(i podobne rozszerzenia) nazywa się globbing w żargonie uniksowym i zwykle jest cechą procesora poleceń (znanego jako „powłoka” w języku uniksowym). Tak więc globbing można stosować również w wielu innych miejscach; wpisz man 7 globw powłoce klasycznej dystrybucji Linuksa (lub zobacz to ), aby uzyskać więcej informacji o globbing.

Na początku Unix globbył faktycznie implementowany przez osobny program o nazwie /etc/glob(dokumentacja tego znajduje się na stronie 10 starego podręcznika UNIX ). Obecnie jest to procedura kodu dostarczana przez biblioteki kodów i jest powszechnie używana przez powłoki. Źródło : Wikipedia .

Katalogi

Dlaczego ls -dlista plików, a także katalogów ...

lsStrona mężczyzna wyjaśnia, dlaczego tak się dzieje, ale z bardzo lakonicznym wyjaśnieniem. Oto próba rozszerzonego wyjaśnienia:

Domyślnie lswyświetla zawartość katalogów, gdy podano ich nazwy, i zrobi to samo w przypadku dowiązań symbolicznych do katalogów. -dOpcja oznacza, „gdy imię (imiona) z katalogu (ach)” (które mogą być również podawane w sposób dorozumiany przez globBing) , pokazują tylko _name_s z katalogu (ach), ale nie ich zawartość. Podobnie, jeśli podano (jawnie lub niejawnie ) nazwy dowiązań symbolicznych do katalogów , należy podać nazwę pliku dowiązania symbolicznego, a nie zawartość katalogu, do którego się odwołuje.

O -dile wiem, ta opcja nie ma nic wspólnego z tym, które przedmioty są na liście; można to zrobić (źródło: tutaj ) o find, tak: find . -maxdepth 1 -type d. Nie jestem pewien, czy jest to dobry sposób tylko z GNU ls. Oto kilka przykładów użycia findpolecenia.

Podsumowując: domyślnie lspokazuje zawartość katalogów po podaniu nazwy ścieżki. -dzmienia to zachowanie, pokazując tylko nazwę katalogu, tak jak w przypadku standardowego pliku.


3

Dokumentacja nie mówi, że wyszczególnia tylko pozycje katalogu bur, ale kiedy lsotrzymuje nazwę katalogu, wyświetla pozycję dir zamiast jej zawartości. Najlepszym sposobem na zrozumienie jest przykład:

> {ice} ~ :10:47 % ls -l / 
total 97
drwxr-xr-x   2 root root  4096 May  3 00:27 bin
drwxr-xr-x   4 root root  1024 May  3 14:17 boot
drwxr-xr-x   2 root root  4096 Apr 29 13:44 cdrom
drwxr-xr-x  18 root root  4420 May  9 09:58 dev
...
lrwxrwxrwx   1 root root    33 May  3 14:16 vmlinuz -> boot/vmlinuz-3.9.0-030900-generic
lrwxrwxrwx   1 root root    29 May  3 11:07 vmlinuz.old -> boot/vmlinuz-3.8.0-19-generic
> {ice} ~ :10:47 % ls -ld /
drwxr-xr-x 25 root root 4096 May  3 14:16 /

2

Dokumentacja jest częścią powłoki . W szczególności powłoka wykonuje różne rozszerzenia i podstawienia w określonej kolejności przed wykonaniem polecenia.

Sekwencja rozszerzeń słów dla powłoki zgodnej z Bourne to:

  1. Rozszerzenie Tilde
  2. Rozszerzenie parametru
  3. Zmiana polecenia
  4. Rozbudowa arytmetyczna
  5. Podział pola
  6. Rozszerzenie nazwy ścieżki
  7. Usunięcie oferty

Tak więc lspolecenie nawet nie widzi *znaków, argumenty są już rozszerzone o wszystkie pliki pasujące do a*wzorca globu. W przeciwieństwie do systemu Windows, w którym każde polecenie wymagające globowania nazw plików musi implementować tę funkcję samodzielnie.


1

Kluczowym słowem, którego potrzebujesz ( man bash), jest „rozszerzenie nazwy ścieżki”.


3
bardziej jak „rozszerzenie nazwy ścieżki” lub „generowanie nazwy pliku”. Powiązane z „dopasowaniem wzorca”, ale nie to samo.
Stéphane Chazelas,

@StephaneChazelas Rzeczywiście, ale „dopasowanie wzorca” jest podsekcją „rozwijania nazwy ścieżki” na stronie podręcznika, podczas gdy „Generowanie nazwy pliku” w ogóle tam nie występuje (tylko w dokumencie informacyjnym).
Hauke ​​Laging
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.