How can I make iconv replace the input file with the converted output?
This isn't working because iconv
first creates the output file (since the file already exists, it truncates it), then starts reading its input file (which is now empty). Most programs behave this way.
Create a new, temporary file for the output, then move it into place.
for file in *.php
do
iconv -f cp1251 -t utf8 -o "$file.new" "$file" &&
mv -f "$file.new" "$file"
done
If your platform's iconv
doesn't have -o
, you can use a shell redirection to the same effect.
for file in *.php
do
iconv -f cp1251 -t utf8 "$file" >"$file.new" &&
mv -f "$file.new" "$file"
done
Colin Watson's sponge
utility (included in Joey Hess's moreutils) automates this:
for file in *.php
do
iconv -f cp1251 -t utf8 "$file" | sponge "$file"
done
This answer applies not just to iconv
but to any filter program. A few special cases are worth mentioning:
- GNU sed and Perl
-p
have a-i
option to replace files in place. - If your file is extremely large, your filter is only modifying or removing some parts but never adding things (e.g.
grep
,tr
,sed 's/long input text/shorter text/'
), and you like living dangerously, you may want to genuinely modify the file in place (the other solutions mentioned here create a new output file and move it into place at the end, so the original data is unchanged if the command is interrupted for any reason).
An alternative is recode
, which uses the libiconv library for some conversions. Its behavior is to replace the input file with the output, so this will work:
for file in *.php
do
recode cp1251..utf8 "$file"
done
As recode
accepts multiple input files as parameter, you can spare the for
loop:
recode cp1251..utf8 *.php
For now
find . -name '*.php' -exec iconv -f CP1251 -t UTF-8 {} -o {} \;
works like a charm