Unterverzeichnisse nur n-stufig auflisten

Unterverzeichnisse nur n-stufig auflisten

Festival speichert Voicepack-Daten in der folgenden Beispielverzeichnisstruktur:

/usr/share/festival/voices/<language>/<voicepack name>

Was ist der einfachste Einzeiler (vorzugsweise mit ) , um nur die 's in allen möglicherweise zahlreichen Unterverzeichnissen lsauszudrucken ?<voicepack name><language>

Antwort1

Ich verwende Fedora und diese Sprachpakete befinden sich an einem etwas anderen Ort:

$ ls /usr/share/festival/lib/voices/*/ -1 | grep -vE "/usr|^$"
kal_diphone
ked_diphone
nitech_us_awb_arctic_hts
nitech_us_bdl_arctic_hts
nitech_us_clb_arctic_hts
nitech_us_jmk_arctic_hts
nitech_us_rms_arctic_hts
nitech_us_slt_arctic_hts

Sie können dies einfach wie folgt ändern:

$ ls /usr/share/festival/voices/*/ -1 | grep -vE "/usr|^$"

Verwenden von „find“

Die Verwendung lsin dieser Weise wird normalerweise missbilligt, da die Ausgabe lsschwer zu analysieren ist. Verwenden Sie besser den findBefehl wie folgt:

$ find /usr/share/festival/lib/voices -maxdepth 2 -mindepth 2 \
    -type d -exec basename {} \;
nitech_us_awb_arctic_hts
nitech_us_bdl_arctic_hts
nitech_us_slt_arctic_hts
nitech_us_jmk_arctic_hts
nitech_us_clb_arctic_hts
nitech_us_rms_arctic_hts
ked_diphone
kal_diphone

Details zu „Finden“ und „Basisname“

Dieser Befehl funktioniert, indem er eine Liste vollständiger Pfade zu Dateien erstellt, die in Bezug auf dieses Verzeichnis genau 2 Ebenen tief liegen:

/usr/share/festival/lib/voices

Diese Liste sieht folgendermaßen aus:

$ find /usr/share/festival/lib/voices -maxdepth 2 -mindepth 2 
/usr/share/festival/lib/voices/us/nitech_us_awb_arctic_hts
/usr/share/festival/lib/voices/us/nitech_us_bdl_arctic_hts
/usr/share/festival/lib/voices/us/nitech_us_slt_arctic_hts
/usr/share/festival/lib/voices/us/nitech_us_jmk_arctic_hts
/usr/share/festival/lib/voices/us/nitech_us_clb_arctic_hts
/usr/share/festival/lib/voices/us/nitech_us_rms_arctic_hts
/usr/share/festival/lib/voices/english/ked_diphone
/usr/share/festival/lib/voices/english/kal_diphon

Aber wir wollen den letzten Teil dieser Verzeichnisse, den Blattknoten. Daher können wir verwenden, basenameum ihn auszuwerten:

$ basename /usr/share/festival/lib/voices/us/nitech_us_awb_arctic_hts
nitech_us_awb_arctic_hts

Wenn wir alles zusammenfassen, können wir den findBefehl dazu bringen, jedes 2-Ebenen-tiefe Verzeichnis an den basenameBefehl zu übergeben. Die Notation basename {}ist das, was diese Basisnamenkonvertierungen durchführt. Find ruft sie über seinen -execSchalter auf.

Antwort2

Am einfachsten ist

ls -d /usr/share/festival/voices/*/*

Dies wird von der Shell in alle Unterverzeichnisse /usr/share/festival/voices/und dann in den Inhalt jedes dieser Unterverzeichnisse erweitert.

Wenn Sie, wie Ihr Titel nahelegt, nur bis zu einer bestimmten Ebene absteigen möchten, mit einigen Implementierungen von findGNU und einigen BSD:

find /usr/share/festival/voices/ -mindepth 2 -maxdepth 3 -type d

Damit werden alle Verzeichnisse ( ) gefunden -type d, die in einem Unterverzeichnis von /usr/share/festival/voices/liegen, mindepth 2aber nicht tiefer als 3 Ebenen ( maxdepth 3) sind. Von man find:

   -maxdepth levels
          Descend at most levels (a non-negative integer) levels of direc‐
          tories below the command line arguments.  -maxdepth 0
           means only apply the tests and  actions  to  the  command  line
          arguments.

   -mindepth levels
          Do  not apply any tests or actions at levels less than levels (a
          non-negative integer).  -mindepth  1  means  process  all  files
          except the command line arguments.

Antwort3

Derakzeptierte Antwortbasenamefunktioniert korrekt, ist aber etwas ineffizient, da es für jedes Unterverzeichnis einen neuen Prozess erzeugt :

find /usr/share/festival/lib/voices -maxdepth 2 -mindepth 2 \
    -type d -exec basename {} \;

Wenn möglich, ist es vorzuziehen, integrierte Funktionen zu verwenden, findum den Aufwand für das Erstellen von Prozessen zu vermeiden. findverfügt über eine ziemlich umfangreiche Möglichkeit, seine gedruckte Ausgabe mithilfe der -printfAktion zu ändern. Die Standardaktion -print druckt den gesamten Pfad, aber mithilfe -printfeiner Formatzeichenfolge können Sie Teile des Pfads zum Drucken auswählen. Um nur den Dateinamenteil des Pfads ohne die führenden Verzeichnisse zu extrahieren (wie dies der basename Fall ist), lautet die Formatzeichenfolge %f. Um nach jedem Dateinamen eine neue Zeile einzufügen, fügen Sie \nFolgendes ein:

$ find /usr/share/festival/lib/voices -maxdepth 2 -mindepth 2 \
    -type d -printf '%f\n'
nitech_us_awb_arctic_hts
nitech_us_bdl_arctic_hts
nitech_us_slt_arctic_hts
nitech_us_jmk_arctic_hts
nitech_us_clb_arctic_hts
nitech_us_rms_arctic_hts
ked_diphone
kal_diphone

Antwort4

Für jemanden, der Bash verwendet und etwas Einfaches sucht, indem er einfach ls verwendet:

ls -d $PWD/*

Achten Sie beim Erstellen eines Alias ​​(in ~/.bash_aliases oder wo auch immer) darauf, einfache Anführungszeichen zu verwenden:

alias ldf='ls -d $PWD/*'

Wenn Sie es nicht in Anführungszeichen setzen, versucht die Shell, ls auszuführen.

Durch doppelte Anführungszeichen wird der Alias ​​mit dem Wert $PWD zum Zeitpunkt des Alias ​​erstellt.

Sie können $(pwd) verwenden, wenn Sie möchten, aber ich sehe keinen Sinn darin, eine Unter-Shell zu erstellen, wenn Bash $PWD für Sie bereitstellt.

verwandte Informationen