Idealerweise machen Sie das gar nicht so, denn das korrekte Parsen von Dateinamen in einem Shell-Skript ist immer schwierig (korrigieren Sie es für Leerzeichen, Sie werden immer noch Probleme mit anderen eingebetteten Zeichen haben, insbesondere Zeilenumbruch). Dies wird sogar als erster Eintrag auf der BashPitfalls-Seite aufgeführt.
Allerdings gibt es eine Möglichkeit, fast das zu tun, was Sie wollen:
oIFS=$IFS
IFS=$'\n'
find . -name '*.txt' | while read -r i; do
# use "$i" with whatever you're doing
done
IFS=$oIFS
Denken Sie daran, auch $i
zu zitieren bei der Verwendung, um zu vermeiden, dass andere Dinge die Leerzeichen später interpretieren. Denken Sie auch daran, $IFS
einzustellen zurück, nachdem Sie es verwendet haben, da dies nicht später zu verwirrenden Fehlern führen wird.
Dies hat eine weitere Einschränkung:was in while
passiert -Schleife kann in einer Subshell stattfinden, abhängig von der genauen Shell, die Sie verwenden, sodass variable Einstellungen möglicherweise nicht bestehen bleiben. Die for
Loop-Version vermeidet das aber um den Preis, auch wenn man den $IFS
anwendet Lösung, um Probleme mit Leerzeichen zu vermeiden, dann bekommen Sie Probleme, wenn find
gibt zu viele Dateien zurück.
Irgendwann besteht die richtige Lösung für all dies darin, es in einer Sprache wie Perl oder Python statt in der Shell zu tun.
Verwenden Sie find -print0
und leiten Sie es an xargs -0
weiter , oder schreiben Sie Ihr eigenes kleines C-Programm und leiten Sie es an Ihr kleines C-Programm weiter. Das ist was -print0
und -0
wurden erfunden für.
Shell-Skripte sind nicht der beste Weg, um Dateinamen mit Leerzeichen zu handhaben:Sie können es tun, aber es wird klobig.
Sie können den "internen Feldtrenner" (IFS
) zu etwas anderem als dem Leerzeichen für die Aufteilung der Schleifenargumente, z. B.
ORIGIFS=${IFS}
NL='
'
IFS=${NL}
for i in $(find . -name '*.txt'); do
IFS=${ORIGIFS}
#do stuff
done
IFS=${ORIGIFS}
Ich habe IFS
zurückgesetzt nach seiner Verwendung in find, vor allem, weil es schön aussieht, denke ich. Ich habe keine Probleme darin gesehen, es auf Newline zu setzen, aber ich denke, das ist "sauberer".
Eine andere Methode, je nachdem, was Sie mit der Ausgabe von find
machen möchten , ist entweder direkt -exec
zu verwenden mit dem find
Befehl oder verwenden Sie -print0
und leiten Sie es in xargs -0
. Im ersten Fall find
kümmert sich um das Maskieren des Dateinamens. Im -print0
Fall, find
druckt seine Ausgabe mit einem Nulltrennzeichen und dann xargs
spaltet sich darüber auf. Da kein Dateiname dieses Zeichen enthalten kann (was ich weiß), ist dies auch immer sicher. Dies ist vor allem in einfachen Fällen sinnvoll; und ist normalerweise kein guter Ersatz für eine vollständige for
Schleife.