Wie ordne ich einem Array in Linux Bash ls zu?

82
array=${ls -d */}
echo ${array[@]}  

Ich habe drei Verzeichnisse : ww ee qq. Ich möchte sie in einem Array haben und dann das Array drucken.

Jordin Youssef
quelle
Beantwortet das deine Frage? Dateinamen in ein Array
einlesen

Antworten:

108

Es wäre das

array=($(ls -d */))

BEARBEITEN: Eine allgemeinere Antwort finden Sie in der Lösung von Gordon Davisson (dh wenn Ihre Dateinamen Sonderzeichen enthalten). Diese Antwort ist lediglich eine Syntaxkorrektur.

Aaron Okano
quelle
14
Dies funktioniert nicht richtig, wenn die Verzeichnisnamen Leerzeichen enthalten.
Chepner
1
Um das Problem von Leerzeichen oder Sonderzeichen zu lösen, deklarieren Sie das Array zuerst ohne Werte und verwenden Sie dann die integrierte Funktion ARR+=('$(ls -d */)')zum Bearbeiten von Elementen in einem Array. Verwenden Sie dabei einfache Anführungszeichen, um Sonderzeichen zu verarbeiten und Elemente hinzuzufügen oder zu entfernen Array. Einfache Anführungszeichen behalten die Literalzeichen bei und machen Escapezeichen überflüssig, um sie in Verzeichnisnamen zu behandeln.
Yokai
@ Yokai Dein Vorschlag klingt wunderbar, hat aber unter Ubuntu 16.04 oder MacOs nicht funktioniert. Bash erweitert den Code zwischen den einfachen Anführungszeichen wie folgt: declare -a ARR; ARR+=('$(ls -d "$INPUT_DIR"/*)')Gibt nur zurück$(ls -d $INPUT_DIR/*)
Agile Bean
1
Mein Fehler. Das sollten doppelte Anführungszeichen sein, damit die Befehlsersetzung erweitert werden kann. ARR+=("$(ls -d */)")sollte arbeiten. Wenn nicht, lass es mich wissen.
Yokai
2
@Yokai, das fügt nur ein Element insgesamt hinzu (mit einer Reihe von Zeilenumbrüchen), nicht ein Element pro Verzeichnis.
Charles Duffy
76

Wann immer möglich, sollten Sie es vermeiden, die Ausgabe von zu analysieren ls(siehe Gregs Wiki zu diesem Thema ). Grundsätzlich ist die Ausgabe von lsmehrdeutig, wenn in einem der Dateinamen lustige Zeichen enthalten sind. Es ist normalerweise auch Zeitverschwendung. In diesem Fall wird beim Ausführen ls -d */die Shell */zu einer Liste von Unterverzeichnissen erweitert (was bereits genau das ist, was Sie möchten) und diese Liste als Argumente an übergeben ls -d, die sich jedes einzelne ansehen und sagen: "Ja, das ist ein Verzeichnis alles in Ordnung "und druckt es aus (in einem inkonsistenten und manchmal mehrdeutigen Format). Der lsBefehl macht nichts Nützliches!

Nun, ok, es macht eine Sache, die nützlich ist: Wenn es keine Unterverzeichnisse gibt, */wird es so belassen, wie es ist, lswird nach einem Unterverzeichnis mit dem Namen "*" suchen, es nicht finden, eine Fehlermeldung drucken, die es nicht gibt (bis stderr) und drucken Sie nicht das "* /" (zu stdout).

Der sauberere Weg, ein Array von Unterverzeichnisnamen zu erstellen, besteht darin, glob ( */) zu verwenden, ohne es zu übergeben ls. Um jedoch zu vermeiden, dass "* /" in das Array eingefügt wird, wenn keine tatsächlichen Unterverzeichnisse vorhanden sind, sollten Sie zuerst nullglob festlegen (siehe auch Gregs Wiki ):

shopt -s nullglob
array=(*/)
shopt -u nullglob # Turn off nullglob to make sure it doesn't interfere with anything later
echo "${array[@]}"  # Note double-quotes to avoid extra parsing of funny characters in filenames

Wenn Sie eine Fehlermeldung drucken möchten, wenn keine Unterverzeichnisse vorhanden sind, sollten Sie dies besser selbst tun:

if (( ${#array[@]} == 0 )); then
    echo "No subdirectories found" >&2
fi
Gordon Davisson
quelle
2
Vielen Dank für Ihren Kommentar, obwohl er nicht als Antwort markiert wurde, war er recht informativ und ich schätze ihn.
Jake H
Was ist, wenn Sie /den Namen im Verzeichnis nicht möchten ?
Shinzou
Die im Wiki des Greg beschriebenen Probleme sind keine Dinge, die mit bloßen bedingten Konstrukten nicht einfach zu lösen sind. lsist ein einfacher Befehl. Die Ausgabe erfolgt über Zeichenfolgen. Bash ist übermäßig gut darin, Strings zu analysieren. Die richtige Regex ist alles, was erforderlich ist, um die lsAusgabe sicher zu analysieren .
Yokai
@Yokai Verschiedene Versionen von lsmachen verschiedene Dinge mit lustigen / nicht druckbaren Zeichen in Dateinamen, daher gibt es keine einheitliche Möglichkeit, die Ausgabe in eine Liste von Dateinamen zu analysieren. Und wie gesagt, es macht eigentlich nichts Nützliches: Wenn Sie die Ausgabe von richtig analysieren ls -d */, erhalten Sie genau das, was Sie direkt erhalten würden */(außer wenn es keine Übereinstimmungen gibt und das leicht zu überprüfen ist).
Gordon Davisson
Um es zusammenzufassen: A lazy sysadmin is a good sysadmin.Vielleicht ist meine eigene lsAnalyse spezifisch für die Version, die ich habe oder an die ich gewöhnt bin, aber bisher hatten sie keine Probleme mit den Linux-Distributionen, auf denen ich sie getestet habe. Ich kann nur aus Erfahrung sprechen.
Yokai
7

Dies würde die Dateien in diesen Verzeichnissen Zeile für Zeile drucken.

array=(ww/* ee/* qq/*)
printf "%s\n" "${array[@]}"
konsolebox
quelle