Lösung 1
Die nächste Lösung ist die Verwendung find
mit -print0
und Lesen der Ausgabe mit while read …
:
find -name "*.log" -o -name "*.err" -o -name "*.out" -type f -print0 | while IFS= read -r -d '' logfile; do ...
Verwenden "$logfile"
Sie weiterhin Anführungszeichen, wie Sie es bei der Verwendung von Variablen immer tun sollten.
Lösung 2
Eine andere Lösung wäre, sie überhaupt nicht zu verwenden find
und einfach grep
auf mehreren Dateien laufen zu lassen :
shopt -s nullglob shopt -s globstar grep "api/" **/*.log **/*.err **/*.out
Hier globstar
ermöglicht rekursive Abgleich von Verzeichnissen mit **
. Sie sollten festlegen nullglob
, dass Fehler vermieden werden, wenn eine dieser Dateierweiterungen nicht vorhanden ist.
Dies funktioniert jedoch nur für eine begrenzte Anzahl von Dateien, da Sie möglicherweise die maximale Länge der Befehlszeilenargumente erreichen.
Warum passiert der Fehler?
Sie sollten niemals for
mit der Ausgabe von find
(oder ls
oder einer anderen Funktion, die Dateinamen mit Leerzeichen ausgibt) ausgeführt werden. In diesem Artikel erhalten Sie weitere Informationen, warum dies ein Problem ist und was getan werden kann, um es zu lösen.
Kurz gesagt, Bash teilt Argumente nach Leerzeichen. Stellen Sie sich vor Sie haben drei Dateien, a
, foo bar
und b
, dann würde die Linie evalute an:
for logfile in a foo bar b; do
Offensichtlich wird Bash gesetzt logfile
zu a
, foo
, bar
, und b
, das ist nicht das, was Sie wollten. Wenn Sie die Eingabe manuell angeben könnten for
, würden Sie diese Dateinamen in Anführungszeichen setzen, um das Problem zu lösen.
Um dies automatisch durchzuführen, besteht die Lösung darin, diese Dateinamen mit einem NUL
Zeichen zu begrenzen (was die -print0
Option tut), und dann die Ausgabe basierend auf diesem NUL
Zeichen erneut aufzuteilen (was das -d ''
in read
tut).