Mit find erhalten Sie eine Liste der Verzeichnisnamen

35

Ich weiß, dass ich dies tun kann, um eine Liste der Verzeichnisnamen zu erhalten:

find . -type d -maxdepth 1 

Die Ausgabe sieht folgendermaßen aus:

.
./foo
./bar

Ich bevorzuge die Auflistung ohne ./. Gibt es eine Möglichkeit zu finden, um nur die Rohnamen auszugeben?

Ich habe versucht, die Liste an stat zu senden, um sie zu formatieren, aber das führt zu demselben Ergebnis:

find . -type d -maxdepth 1 -print0 | xargs -0 stat -f '%N'
joachim
quelle
du willst also foo bar ...alles auf einer leitung ohne die ./vor?
Levon
Ist dies nur aus kosmetischen / ästhetischen Gründen oder versuchen Sie, etwas mit der Ausgabe zu tun?
jw013

Antworten:

42

Mit GNU können findSie die -printfOption verwenden:

find . -maxdepth 1 -type d -printf '%f\n'

Wie von Paweł in den Kommentaren vermerkt, wenn Sie nicht möchten, dass das aktuelle Verzeichnis aufgelistet wird, fügen Sie Folgendes hinzu -mindepth 1:

find . -mindepth 1 -maxdepth 1 -type d -printf '%f\n'
Thor
quelle
Ich kann die -printfOption in der neuesten POSIX-Spezifikation nicht erwähnen und frage mich, wie portabel sie ist ...
rahmu
@rahmu: Dies wurde mit GNU find getestet. Keine der printfOptionen wird von POSIX erwähnt und scheint von einigen anderen findVersionen nicht unterstützt zu werden . GNU find kann an den meisten Orten installiert werden, ist also in diesem Sinne portabel.
Thor
1
-mindepth 1.
Fügen
18

Aktualisieren:

Eine kürzere Alternative:

 find . -maxdepth 1 -type d | cut -c 3-

Gibt Ihnen die Namen, einen pro Zeile, ohne Schrägstriche

Levon
quelle
4
@Downvoter .. eine Downvote ohne Erklärung hilft niemandem (OP, SO oder mir). Dies ist eine funktionale Lösung für die Frage von OP. Gerne korrigiere ich einen Fehler, wenn ich darauf hingewiesen oder die Antwort verbessert habe. Dies erfordert jedoch konstruktives Feedback und nicht nur einen anonymen "Klick".
Levon
1
Ich bin derjenige, der abstimmte, als Ihre Antwort das Parsen beinhaltete ls. Gleichzeitig hatte ich einen Link gepostet, warum dies eine schlechte Idee für eine andere Antwort ist, die seitdem gelöscht wurde. Zu der Zeit gab es nur 2 Antworten und der Grund schien offensichtlich. Ich bin froh, dass Sie auf die Mehrdeutigkeit hingewiesen haben, und hier ist meine Erklärung. Ich habe meine Gegenstimme in eine Gegenstimme umgewandelt, weil ich Ihrer aktuellen Antwort zustimme.
Rahmu
@rahmu Eine Erklärung für deine Ablehnung in einer anderen Frage zu geben, ist für mich nicht hilfreich (und nur für dich offensichtlich). Auch wenn dies eine bessere Lösung ist, hat die Lösung, die ich zuvor gepostet hatte, einwandfrei funktioniert (ja, ich kenne Ihren Link "Keine ls verwenden" - aber er gilt nicht in allen Fällen blind). Wenn Sie ein Gegenbeispiel dafür haben, warum meine ursprüngliche Lösung nicht funktioniert hätte, würde ich es gerne wissen (damit ich tatsächlich etwas daraus lernen kann), andernfalls posten Sie nur einen Link und bieten nichts Konstruktives an.
Levon
\nStellen Sie sich vor, es gibt einen in einem Verzeichnis, den Sie nicht mit cut abrufen können (was Sie getan haben, als ich Sie abgelehnt habe). Es gibt nur wenige Fälle, in denen sich lsdas nicht gefährlich verhält, und es ist fast immer sicherer, einen anderen Weg zu wählen.
Rahmu
9

Mit GNU find können Sie -mindepth verwenden, um zu verhindern, dass die Suche mit dem aktuellen Verzeichnis übereinstimmt:

find . -type d -maxdepth 1 -mindepth 1

Da Sie dies nicht rekursiv tun, können Sie einen Bash-Glob verwenden:

echo */

Durch das Hinzufügen eines abschließenden / zu einem Glob werden nur Verzeichnisse abgeglichen.

Jordanien
quelle
1
*/vermisst Punktedateien und enthält Symlinks. Dies kann ein Problem sein oder auch nicht.
Gilles 'SO - hör auf böse zu sein'
@Gilles - Es fehlen immer Symlinks, aber die Punktedateien hängen davon ab, ob dotglob gesetzt ist oder nicht.
Jordanien
6

Lassen Sie uns seddiese beiden Zeichen entfernen:

find . -maxdepth 1 -type d | sed -e 's/^\.\///'
Birei
quelle
6

Ich würde lieber verwenden:

 find ./ -type d -maxdepth 1 -exec basename {} \;
user1293137
quelle
2

Ich benutze normalerweise:

find * -type d

Aber ich weiß nicht, ob es der richtige Weg ist, das zu tun, was Sie wollen.

Francesco Turco
quelle
1
Wenn Sie die Shell alle Dateinamen erweitern lassen möchten, warum sollten Sie find überhaupt verwenden?
Jordanien
@jordanm Nur Verzeichnisse auswählen. echo */würde das selbe tun, mehr oder weniger (es fehlen dot files und symlinks), aber dann würde joachim fragen, wie man das final entfernt /.
Gilles 'SO - hör auf, böse zu sein'
0

Unter AIX funktioniert der Parameter 'maxdepth' nicht.

Im Allgemeinen funktioniert das für mich:

find ./ -type d | cut -d"/" -f2 | sort -u

user1656294
quelle
0

Was Sie suchen, heißt basename, es ignoriert die Unix-Verzeichnisstruktur

Beispiel unten:

find /any/path/you/want -maxdepth 1 -type d -exec basename {} \;

Es schließt für die Ausgabe sogar den Pfad dir aus, so dass es nicht mehr erforderlich ist, cd den Befehl auszuführen


Einige zusätzliche Informationen:

Ich würde -execals Argument übergeben, um stattdessen einen |anderen Befehl für die Ausgabe zu finden (um zu vermeiden, dass der zweite Befehl über jede Ausgabezeile geht, obwohl dies je nach Ausgabe die Leistung des Skripts verbessern könnte).

HINWEIS: Die findOptionen sind nicht positionsabhängig (-maxdepth wirkt sich sowohl auf die zuvor als auch nachher angegebenen Tests aus).

gonzalesraul
quelle