Czy wyświetlasz tylko katalogi korzystające z ls w Bash?


954

To polecenie wyświetla katalogi w bieżącej ścieżce: ls -d */

Co dokładnie robi wzór */?

I jak możemy podać ścieżkę bezwzględną w powyższym poleceniu (np. ls -d /home/alice/Documents), Aby wyświetlić tylko katalogi na tej ścieżce?


7
Zobacz edycję tej odpowiedzi unix.stackexchange.com/a/75047/32647 wyjaśniając, co -dtak naprawdę oznacza.
Evgeni Sergeev,

Odpowiedzi:


991

*/jest wzorcem, który pasuje do wszystkich podkatalogów w bieżącym katalogu ( *pasowałby do wszystkich plików i podkatalogów; /ogranicza to do katalogów). Podobnie, aby wyświetlić listę wszystkich podkatalogów w katalogu / home / alice / Documents, użyjls -d /home/alice/Documents/*/


88
Pamiętaj, że */nie pasuje do żadnych ukrytych folderów. Aby je dołączyć, albo wyraźnie je polub ls -d .*/ */, albo ustaw dotglobopcję w Bash.
Gergő

1
@ytpillai Dzieje się tak, ponieważ nie ma podkatalogów do wyświetlenia. Ten błąd lspojawia się za każdym razem, gdy używasz czegoś, co nie istnieje.
Gordon Davisson

1
Dobra dzięki, właśnie to sprawdziłem i okazuje się, że jedynym katalogiem jest folder główny.
ytpillai

1
@GordonDavisson Komunikat o błędzie można uniknąć dzięki opcji bashshopt -s nullglob

4
@BinaryZebra Ustawienie nullglob uniknęłoby komunikatu o błędzie, ale spowodowałoby jeszcze więcej zamieszania: przy ustawionym nullglob i braku podkatalogów ls */rozwinąłby się do po prostu ls, który wyświetlałby wszystkie pliki w bieżącym katalogu. Jestem pewien, że w tym przypadku nie tego chcesz.
Gordon Davisson

481

Cztery sposoby osiągnięcia tego celu, każdy z innym formatem wyjściowym

1. Korzystanie echo

Przykład: echo */, echo */*/
Oto co mam:

cs/ draft/ files/ hacks/ masters/ static/  
cs/code/ files/images/ static/images/ static/stylesheets/  

2. Używanie lstylko

Przykład: ls -d */
Oto dokładnie to, co dostałem:

cs/     files/      masters/  
draft/  hacks/      static/  

Lub jako lista (ze szczegółowymi informacjami): ls -dl */

3. Używanie lsigrep

Przykład: ls -l | grep "^d" oto co mam:

drwxr-xr-x  24 h  staff     816 Jun  8 10:55 cs  
drwxr-xr-x   6 h  staff     204 Jun  8 10:55 draft  
drwxr-xr-x   9 h  staff     306 Jun  8 10:55 files  
drwxr-xr-x   2 h  staff      68 Jun  9 13:19 hacks  
drwxr-xr-x   6 h  staff     204 Jun  8 10:55 masters  
drwxr-xr-x   4 h  staff     136 Jun  8 10:55 static  

4. Skrypt Bash (niezalecany w przypadku nazw plików zawierających spacje)

Przykład: for i in $(ls -d */); do echo ${i%%/}; done
oto co mam:

cs  
draft  
files  
hacks  
masters  
static

Jeśli chcesz mieć znak „/” jako znak kończący, polecenie to: for i in $(ls -d */); do echo ${i}; done

cs/  
draft/  
files/  
hacks/  
masters/  
static/

2
NB 3było dla mnie zauważalnie wolniejsze niż inne. W katalogu testowałem: 1.012s, 2.016s, 3 .055s , 4.021s.
izomorfizmy

@ isomorphismes, jak zmierzyłeś czas? Za pomocą jakich środków? Przy okazji, muszę powiedzieć, że nie. 1Jest moim ulubionym.
Albert

Albert, użyłem timefunkcji Unix. /// Zgadzam się, echo */jest mądrzejszy niż ls -d */.
izomorfizmy

9
Dwie drobne rzeczy, na które powinieneś zwrócić uwagę. ls -l | grep "^ d" odfiltrowuje dowiązania symboliczne do katalogów, podczas gdy 'ls -d * /' je wyświetla. Również „ls -d * /” kończy się niepowodzeniem, jeśli w katalogu docelowym nie ma żadnych katalogów.
Zoran Pavlovic

15
Ta 1.opcja spowoduje poważne problemy w przypadku nazw folderów ze spacjami.
Shrikant Sharat

99

Używam:

ls -d */ | cut -f1 -d'/'

To tworzy pojedynczą kolumnę bez końcowego ukośnika - przydatne w skryptach.

Moje dwa centy.


18
-1Opcja na lswyjście będzie w formacie pojedynczej kolumny, a także, jak się ls -1 -d */.
Kalin

3
@ user29020 Należy pamiętać, że -1nadal generuje ukośnik końcowy dla każdego wpisu.
Dennis

Jak dodać to .bashrcjako alias '/'?
RNA

@ RNA spóźnia się z odpowiedzią, ale dla przyszłych ludzi: spróbuj uciec z odwrotnym ukośnikiem? '\/'
Caek

1
Łamie się, jeśli występuje wiodący ukośnik. To usuwa tylko końcowe ukośniki:| sed -e 's-/$--'
Victor Sergienko

62

Dla wszystkich folderów bez podfolderów:

find /home/alice/Documents -maxdepth 1 -type d

Dla wszystkich folderów z podfolderami:

find /home/alice/Documents -type d

2
Aby dopasować pytanie (ale dołączyć pliki kropkowe), pierwszym powinno być: w find /home/alice/Documents -maxdepth 1 -mindepth 1 -type dprzeciwnym razie dołączasz /home/alice/Documentssię. Aby dołączyć dowiązania symboliczne do katalogów, prefiks-L
jhnc

Wydaje się, że są to najrozsądniejsze rozwiązania, ponieważ find jest narzędziem stworzonym do tego zadania. Możesz wykluczyć pierwszy wynik - ./ dla bieżącego katalogu - przesyłając potokiem do grep -v '^ \ ./$'
siliconrockstar

38

4 (więcej) Niezawodne opcje.

Zacytowane gwiazdka *będą interpretowane jako wzorzec (zastępczych) przez powłokę.
Powłoka użyje go do rozszerzenia nazwy ścieżki.
Następnie wygeneruje listę nazw plików pasujących do wzorca.
Prosta gwiazdka będzie pasować do wszystkich nazw plików w PWD (obecny katalog roboczy).
Bardziej złożony wzorzec, który */będzie pasował do wszystkich nazw plików, które kończą się na /.
Tak więc wszystkie katalogi. Dlatego polecenie:

1. - echo.

echo */
echo ./*/              ### avoid misinterpreting filenames like "-e dir"

zostanie rozszerzony (przez powłokę) do echowszystkich katalogów w PWD.


Aby to przetestować: Utwórz katalog ( mkdir) o nazwie jak test-dir i cddo niego:

mkdir test-dir; cd test-dir

Utwórz kilka katalogów:

mkdir {cs,files,masters,draft,static}   # safe directories.
mkdir {*,-,--,-v\ var,-h,-n,dir\ with\ spaces}  # some a bit less secure.
touch -- 'file with spaces' '-a' '-l' 'filename'    # and some files:

Polecenie echo ./*/pozostanie niezawodne nawet w przypadku plików o nieparzystych nazwach:

./--/ ./-/ ./*/ ./cs/ ./dir with spaces/ ./draft/ ./files/ ./-h/
./masters/ ./-n/ ./static/ ./-v var/

Ale spacje w nazwach plików sprawiają, że czytanie jest trochę mylące.


Jeśli zamiast tego echoużywamy ls, powłoka wciąż rozwija listę nazw plików. Powłoka jest powodem, aby uzyskać listę katalogów w PWD. -dOpcja lssprawia, że listy niniejszy wpis w katalogu zamiast zawartości każdego katalogu (jak przedstawiono domyślnie).

ls -d */

Jednak to polecenie jest (nieco) mniej niezawodne. Nie powiedzie się z wymienionymi powyżej nieparzystymi plikami. Dusi się kilkoma nazwami. Musisz wymazywać jeden po drugim, aż znajdziesz te, które mają problemy.

2. - ls

GNU lszaakceptuje --klawisz „koniec opcji” ( ).

ls -d ./*/                     ### more reliable BSD ls
ls -d -- */                    ### more reliable GNU ls

3.-printf

Aby wyświetlić listę każdego katalogu w osobnym wierszu (w jednej kolumnie, podobnie do ls -1), użyj:

$ printf "%s\n" */        ### Correct even with "-", spaces or newlines.

Co więcej, możemy usunąć końcowe /:

$ set -- */; printf "%s\n" "${@%/}"        ### Correct with spaces and newlines.

Taka próba:

$ for i in $(ls -d */); do echo ${i%%/}; done

Nie powiedzie się:

  • niektóre nazwy ( ls -d */), jak pokazano powyżej.
  • będzie mieć wpływ wartość IFS.
  • podzieli nazwy na spacje i tabulatory (domyślnie IFS).
  • każda nowa linia w nazwie uruchomi nowe polecenie echa.

4.- Funkcja

Wreszcie użycie listy argumentów wewnątrz funkcji nie wpłynie na listę argumentów aktualnie działającej powłoki. Po prostu:

$ listdirs(){ set -- */; printf "%s\n" "${@%/}"; }
$ listdirs

przedstawia tę listę:

--
-
*
cs
dir with spaces
draft
files
-h
masters
-n
static
-v var

Te opcje są bezpieczne w przypadku kilku rodzajów nieparzystych nazw plików.


Myślę, że powinieneś zamienić słowo Bezpieczne na Niezawodne. Twój post sprawia, że ​​myślę, że inne rozwiązania są „niebezpieczne” (podatne na zagrożenia lub możliwe do wykorzystania).
Amado Martinez

1
@AmadoMartinez Wykonano ogólne s / bezpieczne / niezawodne /. Lepszy?

21

treePolecenia jest również bardzo przydatny tutaj. Domyślnie wyświetla wszystkie pliki i katalogi na pełnej głębokości, a niektóre znaki ascii pokazują drzewo katalogów.

$ tree
.
├── config.dat
├── data
   ├── data1.bin
   ├── data2.inf
   └── sql
|      └── data3.sql
├── images
   ├── background.jpg
   ├── icon.gif
   └── logo.jpg
├── program.exe
└── readme.txt

Ale jeśli chcielibyśmy uzyskać tylko katalogi, bez drzewa ascii i pełną ścieżkę z bieżącego katalogu, możesz zrobić:

$ tree -dfi
.
./data
./data/sql
./images

Argumentami są:

-d     List directories only.
-f     Prints the full path prefix for each file.
-i     Makes tree not print the indentation lines, useful when used in conjunction with the -f option.

A jeśli chcesz ścieżkę bezwzględną, możesz zacząć od podania pełnej ścieżki do bieżącego katalogu:

$ tree -dfi "$(pwd)"
/home/alice/Documents
/home/alice/Documents/data
/home/alice/Documents/data/sql
/home/alice/Documents/images

Aby ograniczyć liczbę podkatalogów, możesz ustawić maksymalny poziom podkatalogów -L level, np .:

$ tree -dfi -L 1 "$(pwd)"
/home/alice/Documents
/home/alice/Documents/data
/home/alice/Documents/images

Więcej argumentów można zobaczyć w drzewie drzewa


15

Jeśli zastanawiasz się, dlaczego dane wyjściowe z 'ls -d * /' dają dwa końcowe ukośniki, takie jak:

[prompt]$ ls -d */    
app//  cgi-bin//  lib//        pub//

dzieje się tak prawdopodobnie dlatego, że gdzieś w pliku konfiguracyjnym powłoki lub sesji znajduje się alias polecenia ls do wersji ls, która zawiera flagę -F. Ta flaga dołącza znak do każdej nazwy wyjściowej (nie jest to zwykły plik), wskazując na rodzaj rzeczy. Więc jeden ukośnik pochodzi z dopasowania wzorca „* /”, a drugi ukośnik to dołączony wskaźnik typu.

Aby pozbyć się tego problemu, możesz oczywiście zdefiniować inny alias dla ls. Aby jednak tymczasowo nie wywoływać aliasu, możesz poprzedzić polecenie odwrotnym ukośnikiem:

\ ls -d * /


11

Po prostu dodaję to do mojego .bashrcpliku (możesz także wpisać go w wierszu poleceń, jeśli potrzebujesz / chcesz tylko na jedną sesję)

alias lsd='ls -ld */'

wtedy lsd wygeneruje pożądany wynik.


Nie możesz po prostu użyć? ls -l ścieżka | grep dr
jrobertsz66

5
„wtedy lsd wygeneruje pożądany wynik”. Śmieję się
fbafelipe,

1
Z mojego doświadczenia wynika, że ​​daje to wynik.
Todd,

Używam „lad” (wyświetla wszystkie katalogi), a także dołączam „. * /”, Aby uwzględnić również ukryte katalogi. Oczywiście, insynuacje też mnie nie stracą.
DryLabRebel

11

Rzeczywiste lsrozwiązanie, w tym dowiązania symboliczne do katalogów

Wiele odpowiedzi tutaj nie używa ls(lub używa ich tylko w trywialny sposób ls -d, używając symboli wieloznacznych do rzeczywistego dopasowania do podkatalogu. Prawdziwe lsrozwiązanie jest przydatne, ponieważ pozwala na użycie lsopcji sortowania itp.

Z wyłączeniem dowiązań symbolicznych

lsPodano jedno użycie rozwiązania , ale robi ono coś innego niż inne rozwiązania, ponieważ wyklucza dowiązania symboliczne do katalogów:

ls -l | grep '^d'

(możliwe przesyłanie potokowe przez sedlub w awkcelu wyizolowania nazw plików)

W tym dowiązania symboliczne

W (prawdopodobnie bardziej powszechnym) przypadku, w którym należy uwzględnić dowiązania symboliczne do katalogów, możemy skorzystać z -popcji ls, co powoduje, że dodaje on znak ukośnika do nazw katalogów (w tym również dowiązań symbolicznych):

ls -1p | grep '/$'

lub pozbywanie się końcowych ukośników:

ls -1p | grep '/$' | sed 's/\/$//'

Możemy dodawać opcje do lspotrzeb (jeśli używana jest długa lista, -1nie jest już wymagana).

Uwaga: jeśli chcemy końcowych ukośników, ale nie chcemy, aby były podświetlone grep, możemy hackersko usunąć wyróżnienie, opróżniając faktycznie dopasowaną część wiersza:

ls -1p | grep -P '(?=/$)'

9

Jeśli ukryty katalog nie musi być wymieniony, oferuję:

ls -l | grep "^d" | awk -F" " '{print $9}'  

A jeśli trzeba wymienić ukryte katalogi, użyj:

ls -Al | grep "^d" | awk -F" " '{print $9}'

LUB

find -maxdepth 1 -type d | awk -F"./" '{print $2}'

Jeśli chcesz dowiedzieć się więcej awk, spójrz na tę odpowiedź
PHP Learner

W porównaniu z innymi odpowiedziami pierwsza opcja „ls .. | grep ... | awk” wydaje się nadmiernym skryptowaniem.
Lars Nordin

1
Zakładasz, że w katalogach nie ma białych znaków.
Benjamin R,

7

aby wyświetlić listy folderów bez /

ls -d */|sed 's|[/]||g'

2
lubls -d1 */ | tr -d "/"
ccpizza 15.04.15

Nie ma potrzeby wywoływania zewnętrznego polecenia:set -- */; printf "%s\n" "${@%/}"

Lubię rozwiązanie @wholanda. Moje nieco krótsze rozwiązanie to (przetestowane i działa): ls -d * / | sed 's | / || g'
klor

Przydatny jest także alias lsdir: alias lsdirs = "ls -d * / | sed 's | / || g'"
klor


6

Aby wyświetlić tylko katalogi :

ls -l | grep ^d

dla listowania tylko plików :

ls -l | grep -v ^d 

lub też możesz zrobić jako: ls -ld * /


4

Sprawdź, czy pozycja jest katalogiem z test -d:

for i in $(ls); do test -d $i && echo $i ; done

1
Proszę wyjaśnić, co robi ten kod i jak odnosi się do pytania.
Ken YN

1
uruchamia komendę „ls”, a następnie wykonuje pętlę przez test wyjściowy, sprawdzając, czy każdy jest katalogiem, i echo, jeśli jest .. działa, ale istnieją lepsze sposoby
ShoeLace

3

*/ to wzorzec dopasowania nazwy pliku, który pasuje do katalogów w bieżącym katalogu.

Aby wyświetlić tylko katalogi, podoba mi się ta funkcja:

# long list only directories
llod () { 
  ls -l --color=always "$@" | grep --color=never '^d'
}

Umieść go w swoim .bashrc.

Przykłady użycia:

llod       # long listing of all directories in current directory
llod -tr   # same but in chronological order oldest first
llod -d a* # limit to directories beginning with letter 'a'
llod -d .* # limit to hidden directories

UWAGA: pęknie, jeśli skorzystasz z tej -iopcji. Oto poprawka:

# long list only directories
llod () { 
  ls -l --color=always "$@" | egrep --color=never '^d|^[[:digit:]]+ d'
}

3

Do Twojej wiadomości, jeśli chcesz wydrukować wszystkie pliki w wielu wierszach, możesz zrobić, ls -1aby wydrukować każdy plik w osobnej linii. plik1 plik2 plik3


3

Prosta lista bieżącego katalogu, będzie to:

ls -1d ./*/

Czy chcesz to posortować i wyczyścić?

ls -1d ./*/ | cut -c 3- | rev | cut -c 2- | rev | sort

Pamiętaj: wielkie litery mają różne zachowania w tym rodzaju


3

Spróbuj tego. Działa dla wszystkich dystrybucji Linuksa.

ls -ltr | grep drw

4
ls -l | grep '^d' | awk '{print $9}'
dw1

2

Jednoliniowa lista katalogów tylko z „tutaj”.

Z liczbą plików.

for i in `ls -d */`; do g=`find ./$i -type f -print| wc -l`; echo "Directory $i contains $g files."; done

2

Częściowo rozwiązałem:

cd "/path/to/pricipal/folder"

for i in $(ls -d .*/); do sudo ln -s "$PWD"/${i%%/} /home/inukaze/${i%%/}; done

ln: «/home/inukaze/./.»: can't overwrite a directory
ln: «/home/inukaze/../..»: can't overwrite a directory
ln: accesing to «/home/inukaze/.config»: too much symbolics links levels
ln: accesing to «/home/inukaze/.disruptive»: too much symbolics links levels
ln: accesing to «/home/inukaze/innovations»: too much symbolics links levels
ln: accesing to «/home/inukaze/sarl»: too much symbolics links levels
ln: accesing to «/home/inukaze/.e_old»: too much symbolics links levels
ln: accesing to «/home/inukaze/.gnome2_private»: too much symbolics links levels
ln: accesing to «/home/inukaze/.gvfs»: too much symbolics links levels
ln: accesing to «/home/inukaze/.kde»: too much symbolics links levels
ln: accesing to «/home/inukaze/.local»: too much symbolics links levels
ln: accesing to «/home/inukaze/.xVideoServiceThief»: too much symbolics links levels

Cóż, to redukuje do mnie, część burmistrza :)


2

Dodając, aby zatoczyć koło, aby odzyskać ścieżkę każdego folderu, użyj kombinacji odpowiedzi Alberta oraz Gordansa, które powinny być całkiem przydatne.

for i in $(ls -d /pathto/parent/folder/*/); do echo ${i%%/}; done

Wynik:

/pathto/parent/folder/childfolder1/
/pathto/parent/folder/childfolder2/
/pathto/parent/folder/childfolder3/
/pathto/parent/folder/childfolder4/
/pathto/parent/folder/childfolder5/
/pathto/parent/folder/childfolder6/
/pathto/parent/folder/childfolder7/
/pathto/parent/folder/childfolder8/


1

Oto, czego używam do wyświetlania tylko nazw katalogów:

ls -1d /some/folder/*/ | awk -F "/" "{print \$(NF-1)}"

1

Aby odpowiedzieć na pierwotne pytanie, */nie ma to nic wspólnego z samym sobą ls; odbywa się to przez powłokę / Bash, w procesie znanym jako globbing .

Właśnie dlatego echo */i ls -d */wyprowadzaj te same elementy. ( -dFlaga powoduje lswyświetlanie nazw katalogów, a nie zawartości katalogów.)


1

Oto odmiana wykorzystująca drzewo, które wyświetla nazwy katalogów tylko w osobnych wierszach, tak, to brzydkie, ale hej, to działa.

tree -d | grep -E '^[├|└]' | cut -d ' ' -f2

lub z awk

tree -d | grep -E '^[├|└]' | awk '{print $2}'

Jest to jednak prawdopodobnie lepsze i zachowa /nazwę katalogu po.

ls -l | grep "^d" | awk '{print $9}'

to wygląda jak koreańskie!
Paschalis

0
file *|grep directory

O / P (na mojej maszynie) -

[root@rhel6 ~]# file *|grep directory
mongo-example-master:    directory
nostarch:                directory
scriptzz:                directory
splunk:                  directory
testdir:                 directory

Powyższe dane wyjściowe można bardziej udoskonalić za pomocą cut.

file *|grep directory|cut -d':' -f1
mongo-example-master
nostarch
scriptzz
splunk
testdir

* could be replaced with any path that's permitted
 file - determine file type
 grep - searches for string named directory
 -d - to specify a field delimiter
 -f1 - denotes field 1

0

Najkrótsze polecenie w historii (właściwie włamanie) do wyświetlania tylko katalogów. Wpisz bezwzględną ścieżkę lub ścieżkę względną interesującego katalogu i naciśnij Enter, aby wejść do interesującego katalogu. Teraz wpisz cdi naciśnij klawisz Tab . Wyświetlane są tylko katalogi.

user@ubuntu:~/Desktop$cd <tab key>

Powyższe polecenie powinno teraz wyświetlać tylko foldery na pulpicie . Rzeczywiście najkrótszy.


Zakłada się, że autouzupełnianie jest włączone i może nie działać we wszystkich przypadkach. Ponadto, jeśli chcesz coś z tym zrobić, np. Potokować wyjście w coś, to nie zadziała. Ale aby zobaczyć wynik, na pewno działa szybko i łatwo.
lacostenycoder

Doskonały! Usunąłem „.” A potem zadziałało
2060451
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.