Polecenie „ls -d” nie wyświetla katalogów. Czy istnieje sposób, aby „ls” wyświetlał tylko katalogi zamiast plików i katalogów?

44

Czy istnieje sposób, aby lswyświetlać tylko katalogi zamiast plików i katalogów?

Ze strony podręcznika:

   -d, --directory
          list directory entries instead of contents, and do not  derefer
          ence symbolic links

Więc jeśli wpisuję go w /katalogu, spodziewam się zobaczyć tylko katalogi. Zamiast tego pokazuje „.”

$ cd /
$ ls -d
.

Oczekiwałem, ls -dże pokażę to:

$ ls -d
bin    data  home        opt    sbin  sys      var
boot   dev   lib         media  proc  selinux  tmp
cdrom  etc   lost+found  mnt    root  srv      usr

Czy istnieje sposób, aby lswyświetlać tylko katalogi zamiast plików i katalogów?

nelaaro
źródło
17
LSD może być bardzo mylące.
boehj 10.10.11
2
@jin ls -d * / działa. Ale dlaczego muszę „* /”, aby uzyskać wyjście, którego chcę.
nelaaro,
8
@nelaar -dnie oznacza tylko listy katalogów, oznacza to, że nie ma listy zawartości katalogu. Spróbuj wpisać, ls */a zobaczysz zawartość wszystkich katalogów.
Jin
2
Mam ldiralised się ls -d */w moje .bashrc, aby to ułatwić ...
DQdlM
1
Mogę dać ci mnóstwo informacji, ale ani jednej flagi tylko do pokazania katalogów ...
DimiDak

Odpowiedzi:

50

Twoje oczekiwania są oparte na DOS Think / Windows Think i są błędne. W MS-DOS, Windows i rzeczywiście w kilku innych systemach operacyjnych IBM / Microsoft, interpretacja symboli zastępczych odbywa się przez samą komendę, a /aopcje takie jak opcja dirdziałają jako filtry atrybutów podczas ekspansji symboli zastępczych. dirrozwija znaki wieloznaczne, takie jak *, które interpreter poleceń przekazuje do niego w stanie, w jakim są, a jeśli /ajest określony, stosuje odpowiednie filtry do zwracanych danych. (W niektórych systemach operacyjnych filtry atrybutów można nadać wywołaniu systemowemu w celu wyliczenia katalogu, a jądro systemu operacyjnego lub jego sterowniki systemu plików zastosują je same).

W systemach Unices i Linux rozszerzanie symboli wieloznacznych odbywa się przez powłokę i nie zależy od uprawnień. Kiedy robisz to w katalogu głównym

ls *

to, co lssamo polecenie otrzymuje z powłoki (coś w stylu)

ls bin home opt var boot boot tmp etc utracone + znalezione root usr

Co -d/ --directoryopcja robi to wyłączyć, co zwykle dzieje się dalej . To, co zwykle dzieje się potem, polega na tym, że lsanalizuje kolejno każdy z argumentów, widzi, że są to katalogi i postanawia wyliczyć ich zawartość. W przypadku argumentów, które nazywają pliki, po prostu wypisuje informacje o samym pliku. Dzięki tej -dopcji katalogi są traktowane jak pliki. Tak więc lswypisuje informacje dla każdego z katalogów, które są przekazywane jako argumenty, tak jak zrobiłby to, gdyby były plikami.

Nie -d jest to więc opcja „drukuj tylko katalogi”. W rzeczywistości nie tylko nie ma takiej opcji; nie może być takiej opcji. Rozwijanie symboli wieloznacznych odbywa się przez powłokę i ( shprzynajmniej w POSIX ) nie ma sposobu, aby powiedzieć powłoce, aby sprawdzała bity uprawnień i typów plików, gdy rozwija *się do listy nazw. Aby uzyskać listę samych nazw katalogów, konieczne jest albo użycie findpolecenia, jak wyjaśniono ztank1013, lub użycie sztuczki, w której nazwa ścieżki kończąca się ukośnikiem oznacza pozycję katalogu ., jak wyjaśniono przez Jin. ( Jinlewą kończy się lspolecenie otrzymujące argumenty

ls bin / home / opt / var / boot / dev / tmp / etc / lost + found / root / usr /

ponieważ wzorzec */w rzeczywistości dopasowuje nazwy ścieżek do dwóch składników, drugi jest pusty, a więc nie do końca robi to, co było pożądane. W szczególności potraktuje dowiązania symboliczne wskazujące katalogi tak, jakby były katalogami).

Zachowanie ls -dbez a *jest prostym rozszerzeniem powyższego. Trzeba tylko wiedzieć jeszcze jedną rzecz ls: Gdy nie podano żadnych argumentów, zakłada się domyślny argument .. Teraz bez tej -dopcji, wyżej wymienione przewody zachowanie do zawartości katalogu, nazwanych przez .ich wyliczone, a informacje wyświetlane na jego zawartość. Dzięki tej -dopcji katalog .jest traktowany tak, jakby był plikiem, a wyświetlane są jego informacje, a nie ich zawartość.

JdeBP
źródło
3
„nie może być takiej opcji” - to dość mocne stwierdzenie - implementacja takiej opcji jest oczywista: zobacz argument spoza katalogu i zignoruj ​​go. To, czego nie można zaimplementować, to odpowiednik dir /s *.txt[bez uciekania się do cytowania symboli wieloznacznych jak dla znalezienia]
Random832,
6
Zgadza się, ale nie ma logicznego powodu, dla którego ls nie może mieć opcji, która odfiltruje elementy przekazane jako argumenty. Fakt, że „wieloznaczny ekspansji jest oderwane od typu wpisu kontroli” nie ma znaczenia, bo to nie ma nic w ogóle do czynienia z wildcard ekspansji - tylko sprawdzanie typu pozycja, której nie ma powodu, nie można wykonać w całości w ciągu ls. Jeśli ls --color może odcień je zabarwić na niebiesko, ls -F może wstawić / po nich, a ls -l może wstawić „d” w trybie, wówczas inna hipotetyczna opcja może je pominąć. To, że taka opcja nie istnieje, nie oznacza, że ​​„ nie może ”.
Random832,
5
Random832 ma rację: ls może mieć opcję filtrowania plików lub katalogów, co nie wyklucza się wzajemnie w przypadku rozszerzenia powłoki. W ls nie ma warunków wyścigu: może je filtrować, gdy normalnie rejestruje pliki. (Istnieje już wyścig między rozszerzeniem powłoki a ls, FWIW.) Myślę, że rozszerzenie powłoki jest tylko częścią tego powodu: rozszerzenie powłoki (i ogólnie filtrowanie) nie jest zaimplementowane w ls, ponieważ musiałoby zostać zaimplementowane ponownie w cp , mv itp. Unix to „zrób jedną rzecz i zrób to dobrze”. Jeśli potrzebujesz zaawansowanego filtrowania, istnieją do tego narzędzia.
Thanatos,
2
ls -pOpcja dodaje /symbol tylko do katalogów. Nie ma powodu, aby nie rozszerzać możliwości drukowania wyjściowego o coś, co tylko je wyprowadza (a nie ls -p | grep /).
Anne van Rossum
3
@JdeBP, ataki ad-hominem („kiddo”) i arogancja (wszyscy oprócz ciebie nie znają „podstaw Uniksa”) nie należą do dyskusji technicznej. Co więcej, wyciągasz słomkę, gdy argumentujesz, że opcja polecenia nie może kontrolować rozwijania symboli wieloznacznych przez powłokę. Oczywiście, że nie może! Ani Random832, ani Thanatos, ani Anne van Rossum, a nawet samo pytanie w żaden sposób nie wspominają symboli wieloznacznych. Sprzeciw polegał na tym, że tę ls --only-directories .opcję można w lskońcu dodać .
mkalkov,
30

Możesz użyć ls -d */lub ls -d .*/do ukrytych katalogów.

Jin
źródło
sprytna sztuczka za pomocą /!
Mono
Tak, to dobrze. Czy jest jakiś przypadek, w którym to nie działa?
iyrin
5
+1 za udzielenie odpowiedzi w jednym wierszu. Sądzę, że gdzieś zaakceptowana odpowiedź też ją ma.
Calculus Knight
Jak możesz tego użyć w skrypcie, nie będąc już w katalogu?
DimiDak
13

Spróbuj tego

 find . -mindepth 1 -maxdepth 1 -type d

aby uzyskać tylko katalogi pod bieżącą lokalizacją.

ztank1013
źródło
5

Może ci się spodobać również

tree -d 

który starannie wyświetla wszystkie katalogi i podkatalogi z graficznym przedstawieniem struktury drzewa.

fuenfundachtzig
źródło
3
I tylko na jednym poziomie głębokości:tree -dL 1
Anne van Rossum
Niestety nie można wiele połączyć z drzewem. # drzewo -d | grep wc -l (standardowe wejście)
DimiDak
5

Jeśli chcesz zobaczyć katalogi tylko z ls -lopcją szczegółów takich jak (ELL), możesz użyć poniżej:

find -maxdepth 1 -type d -ls;

Powyżej podasz tylko szczegóły, jakie otrzymujesz z -lopcją.

Adnan Bhatti
źródło
1
Może być nawet lepiej użyć, find -maxdepth 1 -type d -exec ls -d {} +aby uzyskać wyjście w zwykłym lsformacie.
mkalkov,
4

Jeśli chcesz wykonać zadanie w inny sposób, spróbuj tego:

ls -l | grep ^d

Chociaż w tej sytuacji wystarczy jedno narzędzie. Linia rur jest zawsze do Twojej dyspozycji. Podoba mi się elastyczność w Linuksie, której życzę.

Bohr
źródło
1
To odfiltruje więcej niż katalogi.
ocodo
2
@ Slomojo, odfiltruje wszystko oprócz katalogów. Co miałeś na myśli?
mkalkov,
Tak, potrzebujesz opcji -l (długiej), aby uprawnienia przewyższały linię. „d” dla katalogu. Dodatkowo dostajesz „długą” listę pozycji katalogu, co jest miłe.
geoO,
1

Mam nadzieję, że to sprostuje twoją potrzebę. Poniższe polecenie wyświetli tylko katalogi w danej ścieżce.

ls -F <path> | grep /

Przykład:

ls -F ~ | grep /
Thiyagu ATR
źródło