Ich versuche, ein Array in Bash der Dateinamen von meiner Kamera aus zu erstellen:
FILES=(2011-09-04 21.43.02.jpg
2011-09-05 10.23.14.jpg
2011-09-09 12.31.16.jpg
2011-09-11 08.43.12.jpg)
Wie Sie sehen können, befindet sich in der Mitte jedes Dateinamens ein Leerzeichen.
Ich habe versucht, jeden Namen in Anführungszeichen zu setzen und mit einem Backslash aus dem Leerzeichen zu entkommen, was jedoch nicht funktioniert.
Wenn ich versuche, auf die Array-Elemente zuzugreifen, wird der Raum weiterhin als Elementbegrenzer behandelt.
Wie kann ich die Dateinamen mit einem Leerzeichen im Namen richtig erfassen?
FILES[0] = ...
? (Edit: Ich habe es gerade getan; funktioniert nicht. Interessant).find . -maxdepth 1 -type f -iname \*.$1 -printf '%f\n'
); für Element in $ {array [@]}; echo $ element; fertigAntworten:
Ich denke, das Problem könnte teilweise darin liegen, wie Sie auf die Elemente zugreifen. Wenn ich ein einfaches mache
for elem in $FILES
, habe ich das gleiche Problem wie Sie. Wenn ich jedoch wie folgt über seine Indizes auf das Array zugreife, funktioniert es, wenn ich die Elemente entweder numerisch oder mit Escapezeichen hinzufüge:Jede dieser Erklärungen von
$FILES
sollte funktionieren:oder
oder
quelle
echo "${FILES[$i]}"
. B. ). Es spielt keine Rolleecho
, aber es wird für alles, was es als Dateinamen verwendet.for f in "${FILES[@]}"
.#
) Symbol in derfor ((i = 0; i < ${#FILES[@]}; i++))
Anweisung?Es muss etwas falsch sein, wie Sie auf die Elemente des Arrays zugreifen. So geht's:
Aus der Bash-Manpage :
Natürlich sollten Sie beim Zugriff auf ein einzelnes Mitglied auch doppelte Anführungszeichen verwenden
quelle
expands to a single word with the value of each array member separated by the first character of the IFS special variable
for elem in "${files[@]}"
während sie habenfor elem in ${files[@]}
- so verwirren die Leerzeichen die Erweiterung und für Versuche, auf den einzelnen Wörtern zu laufen.Sie müssen IFS verwenden, um das Leerzeichen als Elementtrennzeichen anzuhalten.
Wenn Sie auf Basis von trennen möchten. dann mache einfach IFS = "." Hoffe es hilft dir :)
quelle
IFS=""
vor der Array-Konstruktion verschieben .Ich stimme anderen zu, dass es wahrscheinlich ist, wie Sie auf die Elemente zugreifen, die das Problem sind. Das Zitieren der Dateinamen in der Array-Zuordnung ist korrekt:
Wenn Sie ein Array des Formulars
"${FILES[@]}"
in doppelte Anführungszeichen setzen, wird das Array in ein Wort pro Arrayelement aufgeteilt. Darüber hinaus wird kein Wort geteilt.Die Verwendung
"${FILES[*]}"
hat auch eine besondere Bedeutung, verbindet jedoch die Array-Elemente mit dem ersten Zeichen von $ IFS, was zu einem Wort führt, was wahrscheinlich nicht das ist, was Sie wollen.Wenn Sie ein Bare
${array[@]}
oder ein${array[*]}
Subjekt als Ergebnis dieser Erweiterung für eine weitere Wortaufteilung verwenden, erhalten Sie Wörter, die auf Leerzeichen (und alles andere in$IFS
) aufgeteilt sind, anstatt auf ein Wort pro Array-Element.Die Verwendung einer for-Schleife im C-Stil ist ebenfalls in Ordnung und vermeidet die Sorge um die Wortteilung, wenn Sie sich nicht sicher sind:
quelle
Flucht funktioniert.
Ausgabe:
Das Zitieren der Zeichenfolgen erzeugt ebenfalls die gleiche Ausgabe.
quelle
Wenn Sie Ihr Array wie folgt hatten: #! / Bin / bash
Sie würden bekommen:
Ich weiß nicht warum, aber die Schleife zerlegt die Leerzeichen und fügt sie als einzelnes Element ein, selbst wenn Sie sie mit Anführungszeichen umgeben.
Um dies zu umgehen, rufen Sie die Indizes auf, anstatt die Elemente im Array aufzurufen. Dabei wird die vollständige Zeichenfolge verwendet, die in Anführungszeichen eingeschlossen ist. Es muss in Anführungszeichen gesetzt werden!
Dann erhalten Sie:
quelle
Nicht gerade eine Antwort auf das Zitat- / Fluchtproblem der ursprünglichen Frage, aber wahrscheinlich etwas, das für die Operation tatsächlich nützlicher gewesen wäre:
Wo natürlich der Ausdruck an die spezifische Anforderung angepasst werden müsste (z. B.
*.jpg
für alle oder2001-09-11*.jpg
nur für die Bilder eines bestimmten Tages).quelle
Eine andere Lösung ist die Verwendung einer "while" -Schleife anstelle einer "for" -Schleife:
quelle
Wenn Sie sich nicht auf die Verwendung beschränken
bash
, ist die unterschiedliche Behandlung von Leerzeichen in Dateinamen einer der Vorteile der Fischschale . Stellen Sie sich ein Verzeichnis vor, das zwei Dateien enthält: "a b.txt" und "b c.txt". Hier ist eine vernünftige Vermutung für die Verarbeitung einer Liste von Dateien, die mit einem anderen Befehl generiert wurdenbash
, die jedoch aufgrund von Leerzeichen in Dateinamen fehlschlägt:Mit
fish
ist die Syntax nahezu identisch, aber das Ergebnis ist das, was Sie erwarten würden:Es funktioniert anders, weil fish die Ausgabe von Befehlen auf Zeilenumbrüche und nicht auf Leerzeichen aufteilt.
Wenn Sie einen Fall haben, in dem Sie Leerzeichen anstelle von Zeilenumbrüchen aufteilen möchten,
fish
haben Sie eine gut lesbare Syntax dafür:quelle
Ich habe den IFS- Wert und das Rollback zurückgesetzt, wenn ich fertig war.
Mögliche Ausgabe von der Schleife:
quelle