Listen Sie Unterverzeichnisse nur mit einer Tiefe von n auf

58

Festival speichert Voicepack-Daten in der folgenden Beispielverzeichnisstruktur:

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

Was ist der einfachste Einzeiler (am besten mit ls), um nur die <voicepack name>Zeilen in allen potenziell zahlreichen <language>Unterverzeichnissen auszudrucken ?

user66001
quelle

Antworten:

80

Ich bin auf Fedora und diese Voicepacks 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 so ändern:

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

Verwenden Sie find

Die Verwendung lsin diesem Herrenhaus ist in der Regel verpönt, weil die Ausgabe von lsschwer zu analysieren ist. Verwenden Sie den findBefehl besser 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 Fund & Basisname

Dieser Befehl erstellt eine Liste der vollständigen Pfade zu Dateien, die in Bezug auf dieses Verzeichnis genau zwei Ebenen tief sind:

/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

Wir wollen aber den letzten Teil dieser Verzeichnisse, den Blattknoten. So können wir es verwenden, um es basenamezu analysieren:

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

Wenn Sie alles zusammenfassen, können Sie den findBefehl veranlassen, dass jedes Verzeichnis mit einer Tiefe von 2 Ebenen an den basenameBefehl übergeben wird. Die Notation basename {}ist, was diese Basisnamensumwandlungen tun. Find ruft es über den -execSchalter an.

slm
quelle
lol, ziemlich genau die gleiche Antwort, tolle Köpfe und all das :).
Terdon
+1 - Kannst -exec basename {}du es denen erklären , die beim Herausfinden der Aufgaben in die Irre gehen ?
user66001
@ user66001 - lass es mich wissen, wenn das genug erklärt.
slm
@ user66001 - Sie können eine der Antworten akzeptieren, wenn dies Ihr Problem zu Ihrer
Zufriedenheit
1
Der Befehl find ist in 99% der Fälle erforderlich. Limit sowohl max als auch min war der Schlüssel - ich habe nur max. Beispiel: find ~/ -maxdepth 1 -mindepth 1 -type d | xargs du -csh | sort -h Findet die größten Verzeichnisse sortiert nach Größe
Oligofren
23

Das einfachste ist

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

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

Wenn Sie nur auf eine bestimmte Ebene herabsteigen möchten, wie Ihr Titel vorschlägt, mit einigen Implementierungen findwie GNUs und einigen BSDs:

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

Das wird alle Verzeichnisse (finden -type d) , die in einem Unterverzeichnis sind /usr/share/festival/voices/wegen mindepth 2aber nicht tiefer als 3 Stufen nach unten ( maxdepth 3). 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.
terdon
quelle
Ja, es ist, als würde man in einen Spiegel schauen 8-)
slm
+1 Wie ihr beide 2 Stimmen habt, ist interessant. Gegenstimmen erklären jeweils 1;) PS Ich wollte Verzeichnisnamen, also nur ändern -type f, -type dum dies zu lösen, oder? Wartet auch auf die Antwort von -exec basename {}
slm
@ user66001 ja, -type dfindet Verzeichnisse. Das basenameist eine sehr gute Idee, es wird nur der Name gedruckt und der Pfad entfernt. Angenommen, Sie möchten nur Namen, dann sollten Sie das tun. Schauen Sie sich man basenameund auch an man dirname.
terdon
Danke terdon - Entschuldigen Sie, dass Sie nicht als Antwort markiert haben. Fühlte , dass die aktuelle Version von slm 's mehr Informationen für diejenigen hat, die es brauchen.
user66001
1
@ user66001 zuallererst hast du absolut recht, slms ist in der tat besser. Zweitens sollten Sie sich niemals für die Nichtannahme entschuldigen, es kann nur eine geben und diese sollte diejenige sein, die Sie am besten finden :).
Terdon
6

Die akzeptierte Antwort funktioniert ordnungsgemäß, ist jedoch etwas ineffizient, da basenamefür jedes Unterverzeichnis ein neuer Prozess erstellt wird:

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

Wenn möglich, ist es vorzuziehen, eingebaute Funktionen zu verwenden find, um die Kosten für Laichprozesse zu vermeiden. findhat eine ziemlich umfangreiche Möglichkeit, die Druckausgabe mit der -printfAktion zu ändern . Die Standardaktion -print druckt den gesamten Pfad, aber mit -printfeiner Formatzeichenfolge können Teile des Pfads zum Drucken ausgewählt werden. Um nur den Dateinamen des Pfads ohne die führenden Verzeichnisse zu extrahieren (wie es der basename Fall ist), lautet die Formatzeichenfolge %f. Um nach jedem Dateinamen eine neue Zeile einzufügen, gehen Sie \nwie folgt vor:

$ 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
Michael Henry
quelle
+1 Danke für deine Antwort Michael. Ich kann den Vorteil, dies zu tun, auch in Ihrer Antwort sehen, aber angesichts der Arbeit, die in der Antwort von slm steckt, bin ich gespannt, die akzeptierte Antwort zu wechseln. Wenn @slm dies sieht und keine Probleme mit der Auswahl hat, werde ich hierher zurückkehren, um die akzeptierte Antwort zu ändern.
user66001
1
Die Antwort von @ slm ist gut erklärt und deckt das allgemeinere Muster der Verwendung findmit beliebigen externen Befehlen ab. Es ist nur weniger effizient für Operationen, die eingebaut sind find. Ich hatte überlegt, seiner Antwort einen Kommentar hinzuzufügen, aber das erfordert mehr Ansehen als ich. Sie müssen Ihre akzeptierte Antwort nicht ändern, da die aktuell akzeptierte Antwort korrekt, gut erklärt und als Muster für den allgemeineren Fall verwendbar ist. Ich wollte nur darauf hinweisen, dass es für diesen speziellen Fall eine effizientere Methode gibt.
Michael Henry
0

TLDR; für diejenigen, die gerade hierher kommen, basierend auf dem Titel dieser Frage; zu "Unterverzeichnisse nur n Ebene tief auflisten": verwenden

find -maxdepth N

Wo Nist eine Zahl?

Gabriel Staples
quelle