Ich habe ein Bash-Skript, das jede *.php-Datei in einem Verzeichnis aufzählt und iconv
anwendet dazu. Dies wird in STDOUT ausgegeben.
Seit dem Hinzufügen des -o
-Parameter (meiner Erfahrung nach) schreibt tatsächlich eine leere Datei, wahrscheinlich bevor die Konvertierung stattfindet. Wie kann ich mein Skript so anpassen, dass es die Konvertierung durchführt und dann die Eingabedatei überschreibt?
for file in *.php
do
iconv -f cp1251 -t utf8 "$file"
done
Akzeptierte Antwort:
Dies funktioniert nicht, weil iconv
erstellt zuerst die Ausgabedatei (da die Datei bereits existiert, wird sie abgeschnitten) und beginnt dann mit dem Lesen ihrer Eingabedatei (die jetzt leer ist). Die meisten Programme verhalten sich so.
Erstellen Sie eine neue, temporäre Datei für die Ausgabe und verschieben Sie sie dann an ihren Platz.
for file in *.php
do
iconv -f cp1251 -t utf8 -o "$file.new" "$file" &&
mv -f "$file.new" "$file"
done
Wenn das iconv
Ihrer Plattform hat kein -o
, können Sie eine Shell-Umleitung mit demselben Effekt verwenden.
for file in *.php
do
iconv -f cp1251 -t utf8 "$file" >"$file.new" &&
mv -f "$file.new" "$file"
done
Colin Watsons sponge
Dienstprogramm (in Joey Hess' moreutils enthalten) automatisiert dies:
for file in *.php
do
iconv -f cp1251 -t utf8 "$file" | sponge "$file"
done
Diese Antwort gilt nicht nur für iconv
sondern zu jedem Filterprogramm. Einige Sonderfälle sind erwähnenswert:
- GNU sed und Perl
-p
ein-i
haben Option zum Ersetzen von Dateien an Ort und Stelle. - Wenn Ihre Datei extrem groß ist, ändert oder entfernt Ihr Filter nur einige Teile, fügt aber niemals Dinge hinzu (z. B.
grep
,tr
,sed 's/long input text/shorter text/'
) und Sie gerne gefährlich leben, möchten Sie vielleicht die Datei an Ort und Stelle wirklich ändern (die anderen hier erwähnten Lösungen erstellen eine neue Ausgabedatei und verschieben sie am Ende an Ort und Stelle, sodass die Originaldaten unverändert bleiben, wenn der Befehl für unterbrochen wird beliebigen Grund).