Nur Verzeichnisse mit ls in Bash auflisten?


954

Dieser Befehl listet Verzeichnisse im aktuellen Pfad auf: ls -d */

Was genau macht das Muster */?

Und wie können wir den absoluten Pfad im obigen Befehl angeben (z. B. ls -d /home/alice/Documents), um nur Verzeichnisse in diesem Pfad aufzulisten?


7
In der Bearbeitung dieser Antwort unter unix.stackexchange.com/a/75047/32647 wird erläutert, was -dtatsächlich bedeutet.
Evgeni Sergeev

Antworten:


992

*/ist ein Muster, das mit allen Unterverzeichnissen im aktuellen Verzeichnis *übereinstimmt ( würde mit allen Dateien und Unterverzeichnissen übereinstimmen ; das /beschränkt es auf Verzeichnisse). Verwenden Sie ebenfalls, um alle Unterverzeichnisse unter / home / alice / Documents aufzulistenls -d /home/alice/Documents/*/


88
Beachten Sie, dass */keine versteckten Ordner übereinstimmen. Um sie einzuschließen, geben Sie sie entweder explizit wie ls -d .*/ */an oder setzen Sie die dotglobOption in Bash.
Gergő

1
@ytpillai Das passiert, weil es keine Unterverzeichnisse zum Auflisten gibt. Sie erhalten diesen Fehler jedes Mal, wenn Sie ihn lsfür etwas verwenden, das nicht vorhanden ist.
Gordon Davisson

1
Okay, danke, ich habe das gerade überprüft und es stellt sich heraus, dass das einzige Verzeichnis der Stammordner ist.
Ytpillai

1
@ GordonDavisson Die Fehlermeldung könnte mit der Bash-Option vermieden werdenshopt -s nullglob

4
@BinaryZebra Das Setzen von nullglob würde die Fehlermeldung vermeiden, aber noch mehr Verwirrung stiften: Wenn nullglob gesetzt und keine Unterverzeichnisse vorhanden sind, ls */würde es auf just erweitert ls, wodurch alle Dateien im aktuellen Verzeichnis aufgelistet würden . Ich bin mir ziemlich sicher, dass Sie das in diesem Fall nicht wollen.
Gordon Davisson

481

Vier Möglichkeiten, dies zu erreichen, jeweils mit einem anderen Ausgabeformat

1. Verwenden von echo

Beispiel: echo */, echo */*/
Hier ist , was ich habe:

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

2. lsNur verwenden

Beispiel: ls -d */
Hier ist genau das, was ich bekommen habe:

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

Oder als Liste (mit Detailinfo): ls -dl */

3. Verwenden von lsundgrep

Beispiel: ls -l | grep "^d" Folgendes habe ich bekommen:

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. Bash-Skript (Nicht empfohlen für Dateinamen mit Leerzeichen)

Beispiel: for i in $(ls -d */); do echo ${i%%/}; done
Folgendes habe ich bekommen:

cs  
draft  
files  
hacks  
masters  
static

Wenn Sie '/' als Endzeichen haben möchten, lautet der Befehl: for i in $(ls -d */); do echo ${i}; done

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

2
NB. 3war für mich merklich langsamer als die anderen. In dem Verzeichnis, das ich getestet habe: 1.012s, 2.016s, 3 .055s , 4.021s.
Isomorphismen

@isomorphismes, wie hast du die Zeit gemessen? Mit welchen Mitteln? Übrigens muss ich sagen, Nein 1ist mein Favorit.
Albert

Albert, ich habe timedie Unix-Funktion verwendet. /// Ich stimme zu, echo */ist schlauer als ls -d */.
Isomorphismen

9
Zwei kleine Dinge, die Sie beachten sollten. ls -l | grep "^ d" filtert symbolische Links zu Verzeichnissen heraus, während 'ls -d * /' sie anzeigt. Außerdem schlägt 'ls -d * /' fehl, wenn im Zielverzeichnis überhaupt keine Verzeichnisse vorhanden sind.
Zoran Pavlovic

15
Die 1.Option verursacht erhebliche Probleme beim Umgang mit Ordnernamen mit Leerzeichen.
Shrikant Sharat

99

Ich benutze:

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

Dadurch wird eine einzelne Spalte ohne abschließenden Schrägstrich erstellt - nützlich in Skripten.

Meine zwei Cent.


18
Die -1Option für lswird sowohl im einspaltigen Format als auch in ausgegeben ls -1 -d */.
Kalin

3
@ user29020 Sollte beachten, dass -1immer noch ein abschließender Schrägstrich für jeden Eintrag ausgegeben wird.
Dennis

.bashrcWie füge ich hinzu, wenn ich dies als Alias ​​hinzufüge '/'?
RNA

@RNA spät zu antworten, aber für zukünftige Leute: versuchen Sie mit einem Backslash zu entkommen? '\/'
Caek

1
Bricht, wenn es einen führenden Schrägstrich gibt. Dies entfernt nur nachgestellte Schrägstriche:| sed -e 's-/$--'
Victor Sergienko

62

Für alle Ordner ohne Unterordner:

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

Für alle Ordner mit Unterordnern:

find /home/alice/Documents -type d

2
Um der Frage zu entsprechen (aber Punktdateien einzuschließen), sollte die erste lauten: find /home/alice/Documents -maxdepth 1 -mindepth 1 -type dAndernfalls schließen Sie sich /home/alice/Documentsselbst ein. Um Symlinks zu Verzeichnissen aufzunehmen, stellen Sie-L
jhnc

Dies scheint die vernünftigste Lösung zu sein, da find das Werkzeug ist, das tatsächlich für diese Aufgabe entwickelt wurde. Sie können das erste Ergebnis - ./ für das aktuelle Verzeichnis - ausschließen, indem Sie es an grep -v '^ \ ./$'
siliconrockstar

38

4 (mehr) Zuverlässige Optionen.

Ein nicht zitiertes Sternchen *wird von der Shell als Muster (Glob) interpretiert.
Die Shell verwendet es bei der Pfadnamenerweiterung.
Anschließend wird eine Liste von Dateinamen generiert, die dem Muster entsprechen.
Ein einfaches Sternchen entspricht allen Dateinamen im PWD (aktuelles Arbeitsverzeichnis).
Ein komplexeres Muster, */das mit allen Dateinamen übereinstimmt, die auf enden /.
Also alle Verzeichnisse. Deshalb der Befehl:

1.- Echo.

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

wird (durch die Shell) auf echoalle Verzeichnisse im PWD erweitert.


So testen Sie dies: Erstellen Sie ein Verzeichnis ( mkdir) mit dem Namen test-dir und geben cdSie Folgendes ein :

mkdir test-dir; cd test-dir

Erstellen Sie einige Verzeichnisse:

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:

Der Befehl echo ./*/bleibt auch bei ungeraden Dateien zuverlässig:

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

Aber die Leerzeichen in Dateinamen machen das Lesen etwas verwirrend.


Wenn echowir stattdessen lsdie Shell verwenden , wird die Liste der Dateinamen immer noch erweitert. Die Shell ist der Grund, eine Liste der Verzeichnisse im PWD abzurufen. Die -dOption, lsden aktuellen Verzeichniseintrag anstelle des Inhalts jedes Verzeichnisses aufzulisten (wie standardmäßig dargestellt).

ls -d */

Dieser Befehl ist jedoch (etwas) weniger zuverlässig. Bei den oben aufgeführten ungeraden Dateien schlägt dies fehl. Es wird mit mehreren Namen ersticken. Sie müssen eine nach der anderen löschen, bis Sie diejenigen mit Problemen finden.

2.- ls

Die GNU lsakzeptiert die --Taste "Ende der Optionen" ( ).

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

3.-printf

Verwenden Sie Folgendes, um jedes Verzeichnis in einer eigenen Zeile aufzulisten (in einer Spalte, ähnlich wie ls -1):

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

Und noch besser, wir könnten das Nachlaufen entfernen /:

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

Ein Versuch wie dieser:

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

Wird scheitern am:

  • einige Namen ( ls -d */) wie bereits oben gezeigt.
  • wird durch den Wert von beeinflusst IFS.
  • teilt Namen auf Leerzeichen und Tabulatoren (standardmäßig IFS).
  • Jede neue Zeile im Namen startet einen neuen Echo-Befehl.

4.- Funktion

Schließlich wirkt sich die Verwendung der Argumentliste in einer Funktion nicht auf die Argumentliste der aktuell ausgeführten Shell aus. Einfach:

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

präsentiert diese Liste:

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

Diese Optionen sind bei verschiedenen Arten von ungeraden Dateinamen sicher.


Ich denke, Sie sollten das Wort Safe durch Reliable ersetzen. Ihr Beitrag lässt mich denken, dass die anderen Lösungen "unsicher" (anfällig oder ausnutzbar) sind.
Amado Martinez

1
@AmadoMartinez Fertig ein allgemeines s / sicher / zuverlässig /. Besser?

21

Das tree Befehl ist auch hier ziemlich nützlich. Standardmäßig werden alle Dateien und Verzeichnisse bis zu einer vollständigen Tiefe angezeigt, wobei einige ASCII-Zeichen den Verzeichnisbaum anzeigen.

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

Wenn wir jedoch nur die Verzeichnisse ohne den ASCII-Baum und mit dem vollständigen Pfad aus dem aktuellen Verzeichnis abrufen möchten, können Sie Folgendes tun:

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

Die Argumente sind:

-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.

Wenn Sie dann den absoluten Pfad möchten, können Sie zunächst den vollständigen Pfad zum aktuellen Verzeichnis angeben:

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

Um die Anzahl der Unterverzeichnisse zu begrenzen, können Sie die maximale Ebene der Unterverzeichnisse festlegen -L level, z.

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

Weitere Argumente können mit man tree gesehen werden


15

Falls Sie sich fragen, warum die Ausgabe von 'ls -d * /' zwei nachgestellte Schrägstriche ergibt , wie:

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

Dies liegt wahrscheinlich daran, dass Ihre Shell- oder Sitzungskonfigurationsdateien irgendwo den Befehl ls auf eine Version von ls aliasen, die das Flag -F enthält. Dieses Flag fügt jedem Ausgabenamen ein Zeichen hinzu (das ist keine einfache Datei), das angibt, um was es sich handelt. Ein Schrägstrich entspricht also dem Muster '* /', und der andere Schrägstrich ist der angehängte Typindikator.

Um dieses Problem zu beheben, können Sie natürlich einen anderen Alias ​​für ls definieren. Um den Alias ​​jedoch vorübergehend nicht aufzurufen, können Sie dem Befehl einen Backslash voranstellen:

\ ls -d * /


11

Ich füge dies einfach meiner .bashrcDatei hinzu (Sie können es auch einfach in die Befehlszeile eingeben, wenn Sie es nur für eine Sitzung benötigen / möchten).

alias lsd='ls -ld */'

dann erzeugt lsd das gewünschte Ergebnis.


Könntest du nicht einfach benutzen? ls -l Pfad | grep dr
jrobertsz66

5
"dann wird lsd das gewünschte Ergebnis liefern." Ich lache
fbafelipe

1
Nach meiner Erfahrung ergibt sich ein Ergebnis.
Todd

Ich benutze 'lad' (liste alle Verzeichnisse auf) und habe auch '. * /' Eingefügt, um auch versteckte Verzeichnisse einzuschließen. Natürlich geht mir auch die Anspielung nicht verloren.
DryLabRebel

11

Aktuelle lsLösung, einschließlich Symlinks zu Verzeichnissen

Viele Antworten hier verwenden sie nicht wirklich ls(oder verwenden sie nur im trivialen Sinne ls -d, während Platzhalter für den tatsächlichen Unterverzeichnisabgleich verwendet werden. Eine echte lsLösung ist nützlich, da sie die Verwendung von lsOptionen zum Sortieren der Reihenfolge usw. ermöglicht.

Symlinks ausschließen

Es wurde eine Lösung lsangegeben, die sich jedoch von den anderen Lösungen dadurch unterscheidet, dass Symlinks zu Verzeichnissen ausgeschlossen werden:

ls -l | grep '^d'

(möglicherweise Rohrleitungen durch sedoderawk die Dateinamen diese isolieren)

Einschließlich Symlinks

In dem (wahrscheinlich häufigeren) Fall, dass Symlinks zu Verzeichnissen enthalten sein sollten, können wir die -pOption von verwenden ls, wodurch ein Schrägstrich an die Namen von Verzeichnissen (einschließlich der mit Symlinks verknüpften) angehängt wird:

ls -1p | grep '/$'

oder die nachgestellten Schrägstriche loswerden:

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

Wir können nach lsBedarf Optionen hinzufügen (wenn eine lange Liste verwendet wird, -1ist diese nicht mehr erforderlich).

Anmerkung: Wenn wir wollen , Schrägstriche Hinter, aber nicht will , sie hervorgehoben durch grep, können wir hackishly die Markierung entfernen , indem den tatsächlichen angepassten Teil der Linie leer zu machen:

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

9

Wenn ein verstecktes Verzeichnis nicht aufgelistet werden muss, biete ich Folgendes an:

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

Und wenn versteckte Verzeichnisse aufgelistet werden müssen, verwenden Sie:

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

ODER

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

Wenn Sie mehr darüber wissen awkmöchten, schauen Sie sich bitte diese Antwort an
PHP Learner

Im Vergleich zu anderen Antworten scheint die erste Option von "ls .. | grep ... | awk" übermäßiges Scripting zu sein.
Lars Nordin

1
Sie gehen davon aus, dass keine Verzeichnisse Leerzeichen in ihren Namen enthalten.
Benjamin R

7

Ordnerlisten ohne anzeigen /

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

2
oderls -d1 */ | tr -d "/"
ccpizza

Es ist nicht erforderlich, einen externen Befehl set -- */; printf "%s\n" "${@%/}"

Ich mag die Lösung von @wholanda. Meine etwas kürzere Lösung ist (getestet & funktioniert): ls -d * / | sed 's | / || g'
klor

Auch ein lsdir-Alias ​​ist nützlich: alias lsdirs = "ls -d * / | sed 's | / || g'"
klor

6

Hier ist was ich benutze

ls -d1 /Directory/Path/*;


Dies ist eigentlich eine ziemlich gute Lösung, um es Zeile für Zeile anzuzeigen.
Nikolay Frick

Es werden nicht nur Verzeichnisse aufgelistet. Sie müssen einen ls -d1 /Directory/Path/*/
abschließenden

6

Zum Auflisten nur von Verzeichnissen :

ls -l | grep ^d

zum Auflisten nur von Dateien :

ls -l | grep -v ^d 

oder Sie können auch Folgendes tun: ls -ld * /


4

Testen Sie, ob das Element ein Verzeichnis ist mit test -d:

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

1
Bitte erläutern Sie, was dieser Code bewirkt und wie er sich auf die Frage bezieht.
Ken YN

1
Es führt den Befehl 'ls' aus und durchläuft dann den Ausgabetest, wenn es sich um ein Verzeichnis handelt, und das Echo, wenn dies der
Fall

3

*/ ist ein Dateinamen-Übereinstimmungsmuster, das mit Verzeichnissen im aktuellen Verzeichnis übereinstimmt.

Um nur Verzeichnisse aufzulisten, gefällt mir diese Funktion:

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

Legen Sie es in Ihre .bashrc.

Anwendungsbeispiele:

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

HINWEIS: Wenn Sie die -iOption verwenden, wird sie unterbrochen. Hier ist eine Lösung dafür:

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

3

Zu Ihrer Information, wenn Sie alle Dateien mehrzeilig drucken möchten, können Sie eine ls -1ausführen, bei der jede Datei in einer separaten Zeile gedruckt wird. Datei1 Datei2 Datei3


3

Eine einfache Liste des aktuellen Verzeichnisses wäre:

ls -1d ./*/

Möchten Sie es sortiert und sauber?

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

Denken Sie daran: Großgeschriebene Zeichen verhalten sich in der Sortierung unterschiedlich


3

Probier diese. Es funktioniert für alle Linux-Distributionen.

ls -ltr | grep drw

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

2

Einzeiler, um Verzeichnisse nur von "hier" aufzulisten.

Mit Dateizahl.

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

2

Ich habe teilweise gelöst mit:

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

Nun, das reduziert sich auf mich, den Bürgermeister-Teil :)


2

Verwenden Sie eine Kombination aus Alberts Antwort und Gordans, die ziemlich nützlich sein sollte, um den Kreis zu schließen und den Pfad jedes Ordners abzurufen.

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

Ausgabe:

/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

Folgendes verwende ich, um nur Verzeichnisnamen aufzulisten:

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

1

Die ursprüngliche Frage zu beantworten, */hat an sich nichts zu tun ls; Dies geschieht durch die Shell / Bash in einem als Globbing bezeichneten Prozess .

Deshalb echo */und ls -d */geben Sie die gleichen Elemente aus. (Mit dem -dFlag lswerden die Verzeichnisnamen und nicht der Inhalt der Verzeichnisse ausgegeben.)


1

Hier ist eine Variation unter Verwendung eines Baums, der Verzeichnisnamen nur in separaten Zeilen ausgibt. Ja, es ist hässlich, aber hey, es funktioniert.

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

oder mit awk

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

Dies ist jedoch wahrscheinlich besser und behält den /Namen des Nachverzeichnisses bei.

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

das sieht aus wie Koreanisch!
Paschalis

0
file *|grep directory

O / P (auf meiner Maschine) -

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

Die obige Ausgabe kann durch Schneiden weiter verfeinert werden.

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

Der kürzeste Befehl aller Zeiten (eigentlich ein Hack), um nur Verzeichnisse aufzulisten. Geben Sie den absoluten Pfad oder den relativen Pfad des gewünschten Verzeichnisses ein und drücken Sie die Eingabetaste, um das gewünschte Verzeichnis aufzurufen. Geben Sie nun cddie Tabulatortaste ein und drücken Sie sie . Jetzt werden nur die Verzeichnisse angezeigt.

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

Der obige Befehl sollte jetzt nur Ordner in Desktop anzeigen . In der Tat am kürzesten.


Dies setzt voraus, dass die automatische Vervollständigung aktiviert ist und möglicherweise nicht in allen Fällen funktioniert. Auch wenn Sie etwas damit machen wollten, wie die Ausgabe in etwas zu leiten, wird es nicht funktionieren. Aber um nur die Ausgabe zu sehen, stellen Sie sicher, dass sie schnell und einfach funktioniert.
Lacostenycoder

Perfekt! Ich habe das "." Und dann hat es funktioniert
user2060451
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.