Mám bash skript, který vyjmenovává každý soubor *.php v adresáři a aplikuje iconv
k tomu. Toto dostane výstup ve STDOUT.
Od přidání -o
parametr (podle mých zkušeností) ve skutečnosti zapíše prázdný soubor pravděpodobně před tím, než dojde ke konverzi, jak mohu upravit svůj skript tak, aby provedl konverzi a poté přepsal vstupní soubor?
for file in *.php
do
iconv -f cp1251 -t utf8 "$file"
done
Přijatá odpověď:
Toto nefunguje, protože iconv
nejprve vytvoří výstupní soubor (protože soubor již existuje, zkrátí jej), poté začne číst jeho vstupní soubor (který je nyní prázdný). Většina programů se chová tímto způsobem.
Vytvořte nový dočasný soubor pro výstup a poté jej přesuňte na místo.
for file in *.php
do
iconv -f cp1251 -t utf8 -o "$file.new" "$file" &&
mv -f "$file.new" "$file"
done
Pokud iconv
vaší platformy nemá -o
, můžete použít přesměrování shellu ke stejnému efektu.
for file in *.php
do
iconv -f cp1251 -t utf8 "$file" >"$file.new" &&
mv -f "$file.new" "$file"
done
sponge
Colina Watsona nástroj (zahrnutý v moreutils Joeyho Hesse) to automatizuje:
for file in *.php
do
iconv -f cp1251 -t utf8 "$file" | sponge "$file"
done
Tato odpověď platí nejen pro iconv
ale na jakýkoli filtrovací program. Za zmínku stojí několik speciálních případů:
- GNU sed a Perl
-p
mít-i
možnost nahradit soubory na místě. - Pokud je váš soubor extrémně velký, váš filtr pouze upravuje nebo odstraňuje některé části, ale nikdy nepřidává věci (např.
grep
,tr
,sed 's/long input text/shorter text/'
), a rádi žijete nebezpečně, možná budete chtít skutečně upravit soubor na místě (ostatní zde zmíněná řešení vytvoří nový výstupní soubor a přesunou jej na místo na konci, takže původní data se nezmění, pokud je příkaz přerušen z jakéhokoli důvodu).