Ralf Cirksena wrote (Montag, 26. November 2001 09:57):
Hi Thomas,
On 2001-11-25 19:48 GMT, Thomas Hofer
wrote: Es geht auch mit einer for-Schleife, was vielleicht etwas verständlicher ist, aber bei Spaces in Filenames versagt:
for f in `find .`; do sed 's/Tastatur/Keyboard/g' \ <$f >/tmp/replace.$$ && mv /tmp/replace.$$ $f ; done
Was ist mit for f in "`find .`"; do ...?
Das bringt nichts. Durch die doppelten Quotes wird der ganze Output der Backticks auf einmal in f gepackt (es gibt also nur einen Schleifendurchlauf). Vielleicht hast du probehalber so etwas probiert: for f in "`...`";do echo $f;done ...und das hat dann vielleicht so etwas ausgegeben: a b b c d Das sieht zwar richtig aus, jedoch gibt es nur *einen* Schleifendurchlauf, nicht 4, und die Newlines sind alle in f enthalten! (Gib einmal bei jedem Schleifendurchlauf einen Zähler mit aus, dann wirst du das sehen.) Wenn man jetzt, sagen wir mal, mit dieser Methode alle Dateien mit cat ausgeben wollte, passiert folgendes: cat $f expandiert im ersten Durchlauf zu cat "a" "b" "b" "c" "d" ...und damit verlieren wir erst wieder die Quotes um "b b". Die Alternative cat "$f" expandiert dagegen zu cat "a b b c d", was noch weniger sinnvoll ist, da kein File namens "a b b c d" existiert. Mit Quotes allein kommt man hier also nicht weiter. Man kann die Probleme aber ganz leicht mit der Variable IFS (Internal Field Separator) umgehen, die definiert, welche Zeichen Wörter begrenzen. IFS ist normalerweise auf $' \t\n' gesetzt, was bedeutet, daß ein Wort von einem Space, einem Tabulator oder einem Newline begrenzt wird. (Die Quotes $'' bedeuten, daß \t und ähnliches als die jeweiligen Sonderzeichen interpretiert werden) Die Lösung ist nun, einfach vorübergehend das Space aus dem IFS zu nehmen: (IFS=$'\t\n';for f in `...`;do somethingwith $f;done) Der Backtick-Operator liefert (gemäß des vorigen Beispiels) "a\nb b\nc\nd\n" - jetzt werden aber nur noch die \n als Feldbegrenzer angesehen, das Space in "b b" aber nicht mehr, und der String wird im for so geparst: "a" "b b" "c" "d". Die runden Klammern bewirken, daß der Ausdruck in einer sub-Shell ausgeführt wird, wodurch der originale Wert von IFS auf der Ursprungs-Shell erhalten bleibt. Thomas.