git-bash wie mit Leerzeichen in Dateinamen umgegangen wird

1087
Thom

Ich habe folgendes Skript geschrieben, um unter git-bash unter Windows 7 zu laufen:

#!/usr/bin/env sh for logfile in `find -name "*.log" -o -name "*.err" -o -name "*.out"` do echo $logfile grep "api/" "$logfile" done 

Das Problem ist, dass grep verschluckt, wenn ein Dateiname ein Leerzeichen enthält. Ich dachte, die doppelten Anführungszeichen sollten sich darum kümmern, aber es kooperiert nicht.

Ideen?

Alternativ kannst du sagen, was ich versuche. Alle anderen Vorschläge wären willkommen.

1

1 Antwort auf die Frage

3
slhck

Lösung 1

Die nächste Lösung ist die Verwendung findmit -print0und 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 findund einfach grepauf mehreren Dateien laufen zu lassen :

shopt -s nullglob shopt -s globstar grep "api/" **/*.log **/*.err **/*.out 

Hier globstarermö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 formit der Ausgabe von find(oder lsoder 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 barund b, dann würde die Linie evalute an:

for logfile in a foo bar b; do 

Offensichtlich wird Bash gesetzt logfilezu 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 NULZeichen zu begrenzen (was die -print0Option tut), und dann die Ausgabe basierend auf diesem NULZeichen erneut aufzuteilen (was das -d ''in readtut).