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

问题描述 投票:34回答:12

我在OSX上有一个用latin1编码的PHP项目。现在,我需要将文件转换为UTF8。我不是shell编码员,我尝试了一些从Internet找到的东西:

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

但是这不会创建目录结构,并且在运行时给我带来很多错误。谁能提出整洁的解决方案?

shell character-encoding iconv
12个回答
42
投票

您不应该这样使用ls,并且for循环也不适合。另外,目标目录应位于源目录之外。

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/"{}"' \;

17
投票

一些很好的答案,但我发现嵌套目录包含数百个要转换的文件要容易得多:

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

$ vim $(find . -type f)

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

13
投票

这将转换所有扩展名为.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的某些版本似乎在读取输入文件之前创建了输出文件,这意味着,如果输入文件和输出文件具有相同的名称,则在读取输入文件之前,该文件将被空文件覆盖。


11
投票

要将一个完整的目录树从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上测试过。

Btw:使用以下命令检查文件编码:

file -I file.php

以获取编码信息。

希望这会有所帮助。


6
投票

我创建以下脚本,该脚本(i)备份目录“ converted”中的所有tex文件,(ii)检查每个tex文件的编码,并且(iii)仅将ISO-8859中的tex文件转换为UTF-8。 -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

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
投票

在unix.stackexchange.com上,提出了类似的问题,并且用户操作建议重新编码,可以很好地完成技巧。

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

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

1
投票

在图标之前使用mkdir -p "${a%/*}";。>

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


1
投票

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


0
投票

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


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

0
投票

在Windows Git Bash上,通过一些建议的解决方案出现了这些错误:

© www.soinside.com 2019 - 2024. All rights reserved.