我有一个 bash 脚本,它枚举目录中的每个 *.php 文件并应用于iconv
它。这会在 STDOUT 中获得输出。
由于添加-o
参数(根据我的经验)实际上可能在转换发生之前写入一个空白文件,因此我如何调整我的脚本以进行转换,然后覆盖输入文件?
for file in *.php
do
iconv -f cp1251 -t utf8 "$file"
done
答案1
这是行不通的,因为iconv
首先创建输出文件(因为该文件已经存在,所以它会截断它),然后开始读取其输入文件(现在为空)。大多数程序都是这样运行的。
为输出创建一个新的临时文件,然后将其移动到位。
for file in *.php
do
iconv -f cp1251 -t utf8 -o "$file.new" "$file" &&
mv -f "$file.new" "$file"
done
如果您的平台iconv
没有-o
,您可以使用 shell 重定向来达到相同的效果。
for file in *.php
do
iconv -f cp1251 -t utf8 "$file" >"$file.new" &&
mv -f "$file.new" "$file"
done
科林·沃森的sponge
效用(包括在Joey Hess 的 moreutils)自动执行此操作:
for file in *.php
do
iconv -f cp1251 -t utf8 "$file" | sponge "$file"
done
这个答案不仅适用于iconv
任何过滤程序。一些特殊情况值得一提:
- GNU sed 和 Perl
-p
可以-i
选择就地替换文件。 - 如果你的文件非常大,你的过滤器只是修改或删除一些部分,但从不添加东西(例如,,,
grep
),并且你喜欢危险的生活,你可能想真正地tr
sed 's/long input text/shorter text/'
就地修改文件(此处提到的其他解决方案创建一个新的输出文件并将其移至最后的位置,因此如果命令因任何原因中断,原始数据不会更改)。
答案2
另一种方法是recode
,它使用 libiconv 库进行某些转换。它的行为是用输出替换输入文件,所以这将起作用:
for file in *.php
do
recode cp1251..utf8 "$file"
done
由于recode
接受多个输入文件作为参数,因此您可以节省for
循环:
recode cp1251..utf8 *.php
答案3
目前
find . -name '*.php' -exec iconv -f CP1251 -t UTF-8 {} -o {} \;
奇迹般有效
答案4
这里有一个简单的例子。它应该为您提供足够的信息来开始。
#!/bin/bash
#conversor.sh
#Author.....: dede.exe
#E-mail.....: [email protected]
#Description: Convert all files to a another format
# It's not a safe way to do it...
# Just a desperate script to save my life...
# Use it such a last resort...
to_format="utf8"
file_pattern="*.java"
files=`find . -name "${file_pattern}"`
echo "==================== CONVERTING ===================="
#Try convert all files in the structure
for file_name in ${files}
do
#Get file format
file_format=`file $file_name --mime-encoding | cut -d":" -f2 | sed -e 's/ //g'`
if [ $file_format != $to_format ]; then
file_tmp="${unit_file}.tmp"
#Rename the file to a temporary file
mv $file_name $file_tmp
#Create a new file with a new format.
iconv -f $file_format -t $to_format $file_tmp > $file_name
#Remove the temporary file
rm $file_tmp
echo "File Name...: $file_name"
echo "From Format.: $file_format"
echo "To Format...: $to_format"
echo "---------------------------------------------------"
fi
done;