使用iconv将latin-1文件批量转换为utf-8

时间:2010-12-28 08:24:34

标签: shell character-encoding iconv

我在我的OSX上有一个PHP项目,它是在latin1 -encoding中。现在我需要将文件转换为UTF8。我不是一个shell编码器,我尝试过从互联网上找到的东西:

mkdir new  
for a in `ls -R *`; do iconv -f iso-8859-1 -t utf-8 <"$a" >new/"$a" ; done

但是这不会创建目录结构,它会让我在运行时加载错误。任何人都可以提出整洁的解决方案吗?

11 个答案:

答案 0 :(得分:39)

您不应该使用lsfor循环也不合适。此外,目标目录应位于源目录之外。

mkdir /path/to/destination
find . -type f -exec iconv -f iso-8859-1 -t utf-8 "{}" -o /path/to/destination/"{}" \;

无需循环。 -type f选项包括文件并排除目录。

修改

OS {x}版iconv没有-o选项。试试这个:

find . -type f -exec bash -c 'iconv -f iso-8859-1 -t utf-8 "{}" > /path/to/destination/"{}"' \;

答案 1 :(得分:14)

一些好的答案,但我发现在我的情况下使用数百个要转换的文件的嵌套目录会更容易:

警告:这将写入文件,因此请进行备份

$ vim $(find . -type f)

# in vim, go into command mode (:)
:set nomore
:bufdo set fileencoding=utf8 | w

答案 2 :(得分:10)

这将转换所有具有.php文件扩展名的文件 - 在当前目录及其子目录中 - 保留目录结构:

    find . -name "*.php" -exec sh -c "iconv -f ISO-8859-1 -t UTF-8 {} > {}.utf8"  \; -exec mv "{}".utf8 "{}" \;

注意:

要获取预先定位的文件列表,只需运行不带-exec标志的命令(如下所示:find . -name "*.php")。做一个备份是个好主意。

使用这样的sh允许使用-exec进行管道和重定向,这是必要的,因为并非所有版本的iconv都支持-o标志。

.utf8添加到输出的文件名然后将其删除可能看起来很奇怪,但这是必要的。对输出和输入文件使用相同的名称可能会导致以下问题:

  • 对于大型文件(根据我的经验,大约30 KB),它会导致核心转储(或termination by signal 7

  • 某些版本的iconv似乎在读取输入文件之前创建输出文件,这意味着如果输入和输出文件具有相同的名称,则输入文件将被空文件覆盖读取。

答案 3 :(得分:7)

要将一个完整的目录树递归地从iso-8859-1转换为utf-8,包括子目录的创建,上面没有一个简短的解决方案适用于我,因为目标结构没有在目标中创建。根据Dennis Williamsons的回答,我提出了以下解决方案:

find . -type f -exec bash -c 't="/tmp/dest"; mkdir -p "$t/`dirname {}`"; iconv -f iso-8859-1 -t utf-8 "{}" > "$t/{}"' \;

它将在/tmp/dest中创建当前目录子树的克隆(根据您的需要调整),包括所有子目录,并将所有iso-8859-1文件转换为utf-8。在macosx上测试。

顺便说一下:用以下方法检查您的文件编码:

file -I file.php

获取编码信息。

希望这有帮助。

答案 4 :(得分:5)

如果您要转换的所有文件都是.php,您可以使用以下内容,默认情况下是递归的:

for a in $(find . -name "*.php"); do iconv -f iso-8859-1 -t utf-8 <"$a" >new/"$a" ; done

我相信您的错误是由于ls -R也会产生一个输出,该输出可能无法被iconv识别为有效的文件名,例如./my/dir/structure:

答案 5 :(得分:5)

我创建了以下脚本:(i)备份目录中的所有tex文件&#34;转换&#34;,(ii)检查每个tex文件的编码,以及(iii)仅转换为UTF-8 tex ISO-8859-1编码中的文件。

FILES=*.tex
for f in $FILES
do
  filename="${f%.*}"
  echo -n "$f"
#file -I $f
  if file -I $f | grep -wq "iso-8859-1"
  then
    mkdir -p converted
    cp $f ./converted
    iconv -f ISO-8859-1 -t UTF-8 $f > "${filename}_utf8.tex"
    mv "${filename}_utf8.tex" $f
    echo ": CONVERTED TO UTF-8."
  else
    echo ": UTF-8 ALREADY."
  fi
done

答案 6 :(得分:4)

在unix.stackexchange.com上提出了一个类似的问题,并且用户manatwork建议重新编码,这非常好。

我一直在使用它将ucs-2转换为utf-8

recode ucs-2..utf-8 *.txt

答案 7 :(得分:1)

在iconv。

之前使用mkdir -p "${a%/*}";

请注意,当文件名中有空格时,您使用的是潜在危险的for构造,请参阅http://porkmail.org/era/unix/award.html

答案 8 :(得分:0)

find . -iname "*.php" | xargs -I {} echo "iconv -f ISO-8859-1 -t UTF-8 \"{}\" > \"{}-utf8.php\""

答案 9 :(得分:0)

使用Dennis Williamson和Alberto Zaccagni的答案,我想出了以下脚本,该脚本从所有子目录转换指定文件类型的所有文件。然后将输出收集在/path/to/destination

给出的一个文件夹中
mkdir /path/to/destination
for a in $(find . -name "*.php"); 
do 
        filename=$(basename $a);
        echo $filename
        iconv -f iso-8859-1 -t utf-8 <"$a" >"/path/to/destination/$filename"; 
done

函数basename返回没有文件路径的文件名。

替代方案(用户互动): 现在我还创建了一个用户交互式脚本,可以让您决定是要覆盖旧文件还是只重命名它们。还要感谢tbsalling

for a in $(find . -name "*.tex");
do
        iconv -f iso-8859-1 -t utf-8 <"$a" >"$a".utf8 ;
done
echo "Should the original files be replaced (Y/N)?"
read replace
if [ "$replace" == "Y" ]; then
    echo "Original files have been replaced."
    for a in $(find . -name "*.tex.utf8");
        do
            file_no_suffix=$(basename -s .tex.utf8 "$a");
            directory=$(dirname "$a");
            mv "$a" "$directory"/"$file_no_suffix".tex;
        done
else
        echo "Original files have been converted and converted files were saved with suffix '.utf8'"
fi

玩得开心,我将非常感谢任何改进它的评论,谢谢!

答案 10 :(得分:0)

上述答案一切都很好,但如果这是一个“混合”项目,即已经存在UTF8文件,那么我们可能会遇到麻烦,因此这是我的解决方案,我首先检查文件编码。

#!/bin/bash
# file name: to_utf8

# current encoding:
encoding=$(file -i "$1" | sed "s/.*charset=\(.*\)$/\1/")

if [  "${encoding}" = "iso-8859-1" ] || [ "${encoding}" = "iso-8859-2" ]; 
then
echo "recoding from ${encoding} to UTF-8 file : $1"
recode ISO-8859-2..UTF-8 "$1"
fi

#example:
#find . -name "*.php" -exec to_utf8 {} \;