Warum läuft die Ausgabe dieses Echobefehls in mehrere Zeilen?

460
Darren

Ich habe ein Verzeichnis mit Fotos, deren Namen die Uhrzeit und das Datum der Aufnahme sind. Z.B:

~$ ls directory -1 2003-09-15 03.30.33.jpg 2004-05-04 12.45.28.jpg 2004-05-04 12.45.51.jpg 

Wenn ich diesen Befehl jedoch als Teil einer forSchleife ausführen und die Ausgabe wiederholen, werden die Leerzeichen in den Dateinamen als neue Zeilen behandelt:

~$ for pic in `ls directory -1` ; do echo "$pic"; done 2003-09-15 03.30.33.jpg 2004-05-04 12.45.28.jpg 2004-05-04 12.45.51.jpg 

Warum passiert das und wie kann ich damit aufhören?

1

3 Antworten auf die Frage

4
Eric Renouf

Bei den anderen Antworten ist das Problem, wie die Schleife die Ausgabe des lsBefehls verarbeitet. Wenn eine Zeichenfolge in der forSchleife verwendet wird, wie Sie sie haben, wird die Zeichenfolge in verschiedene Wörter aufgeteilt (basierend auf dem Wert von, IFSwie Darren sagt) und unterliegt dem Globbing und dergleichen. Das bedeutet, dass Sie eine Zeichenfolge übergeben, die sowohl durch die Zeile als auch durch die Leerzeichen in der Zeile geteilt wird. Dann wird jedes dieser Wörter der Reihe nach gesetzt pic.

Kamils ​​Vorschlag löst dieses Problem, weil Sie den Glob direkt auf alle Dateinamen erweitern lassen und dann den gesamten Dateinamen zuweisen pic.

Diese Wortaufteilung wird jedoch an allen Stellen erfolgen, an denen Sie die picVariable später verwenden. Wenn Sie dies nicht möchten, setzen Sie sie in doppelte Anführungszeichen. Z.B,

for pic in *; do printf '%s\n' "$pic" done 

um jeden der Namen zu drucken, einen pro Zeile.

3
Kamil Maciorowski

In Ihrem Fall kann einfaches Muschelkügelchen ausreichen:

for pic in * ; do … 

Auf diese Weise vermeiden Sie auch das Parsen, lswas im Allgemeinen keine gute Idee ist .

Ja, das funktioniert besser, danke! Ich habe letztendlich versucht, die Ausgabe in einen Suchbefehl zu installieren, um nach Duplikaten zu suchen, und das funktionierte auch nicht, bis ich Ihre Methode verwendete. Darren vor 6 Jahren 0
1
Darren

Frage beantwortet hier . Die kurze Antwort lautet, diesen Befehl auszuführen:

IFS=$(echo -en "\t\n\0")