iconv 任何编码为 UTF-8
Posted
技术标签:
【中文标题】iconv 任何编码为 UTF-8【英文标题】:iconv any encoding to UTF-8 【发布时间】:2012-04-07 04:03:28 【问题描述】:我正在尝试将 iconv 指向一个目录,无论当前编码如何,所有文件都将转换为 UTF-8
我正在使用这个脚本,但您必须指定您要使用的编码。如何让它自动检测当前的编码?
dir_iconv.sh
#!/bin/bash
ICONVBIN='/usr/bin/iconv' # path to iconv binary
if [ $# -lt 3 ]
then
echo "$0 dir from_charset to_charset"
exit
fi
for f in $1/*
do
if test -f $f
then
echo -e "\nConverting $f"
/bin/mv $f $f.old
$ICONVBIN -f $2 -t $3 $f.old > $f
else
echo -e "\nSkipping $f - not a regular file";
fi
done
终端线
sudo convert/dir_iconv.sh convert/books CURRENT_ENCODING utf8
【问题讨论】:
相关:How to change encoding from Non-ISO extended-ASCII text? 【参考方案1】:也许你正在寻找enca
:
Enca 是一个非常简单的字符集分析器。它检测文本文件的字符集和编码,还可以使用内置转换器或外部库和工具(如 libiconv、librecode 或 cstocs)将它们转换为其他编码。
目前它支持白俄罗斯语、保加利亚语、克罗地亚语、捷克语、爱沙尼亚语、匈牙利语、拉脱维亚语、立陶宛语、波兰语、俄语、斯洛伐克语、斯洛文尼亚语、乌克兰语、中文和一些独立于语言的多字节编码。
请注意,一般来说,当前编码的自动检测是一个困难的过程(相同的字节序列在多种编码中可以是正确的文本)。 enca
根据您告诉它检测的语言使用启发式算法(以限制编码的数量)。您可以使用enconv
到convert text files 进行单一编码。
【讨论】:
您的 Enca 链接无效。这是更新的吗? freecode.com/projects/enca 从那时起,Enca 似乎搬到了 Github。请注意,freecode 站点还链接到不存在的 Gitorious 链接。更新了答案中的链接。 我想知道您的意思是iconv
而不是econv
,因为我在手册中找不到econv
。
语法:enca -x utf8 -L mylanguage file.srt
.
您的版本中的有效语言列表:enca -l languages
... 但是 UBUNTU 在更新时丑,我的 enca --version
是 2005 年!如何升级?【参考方案2】:
您可以使用标准的 gnu utils 文件和 awk 获得所需的内容。示例:
file -bi .xsession-errors
给我:
"text/plain; charset=us-ascii"
所以file -bi .xsession-errors |awk -F "=" 'print $2'
给我
"us-ascii"
我在这样的脚本中使用它:
CHARSET="$(file -bi "$i"|awk -F "=" 'print $2')"
if [ "$CHARSET" != utf-8 ]; then
iconv -f "$CHARSET" -t utf8 "$i" -o outfile
fi
【讨论】:
file
使用的启发式方法可能相当粗糙。小心。【参考方案3】:
编译所有这些。进入目录,创建dir2utf8.sh
:
#!/bin/bash
# converting all files in a dir to utf8
for f in *
do
if test -f $f then
echo -e "\nConverting $f"
CHARSET="$(file -bi "$f"|awk -F "=" 'print $2')"
if [ "$CHARSET" != utf-8 ]; then
iconv -f "$CHARSET" -t utf8 "$f" -o "$f"
fi
else
echo -e "\nSkipping $f - it's a regular file";
fi
done
【讨论】:
【参考方案4】:这里是my solution,用于使用recode 和uchardet 放置所有文件:
#!/bin/bash
apt-get -y install recode uchardet > /dev/null
find "$1" -type f | while read FFN # 'dir' should be changed...
do
encoding=$(uchardet "$FFN")
echo "$FFN: $encoding"
enc=`echo $encoding | sed 's#^x-mac-#mac#'`
set +x
recode $enc..UTF-8 "$FFN"
done
将其放入convert-dir-to-utf8.sh
并运行:
bash convert-dir-to-utf8.sh /pat/to/my/trash/dir
请注意,sed
是此处用于 mac 编码的解决方法。
许多不常见的编码需要这样的解决方法。
【讨论】:
uchardet
保存了我的脚本
提示:备份您的文件并使用合并工具检查/比较更改。可能会出现问题!
recode
除了this fork之外似乎不再维护【参考方案5】:
查看可用于在 linux cli 中进行数据转换的工具:https://www.debian.org/doc/manuals/debian-reference/ch11.en.html
此外,还有一个任务是找出iconv
中可用的完整编码列表。只需运行iconv --list
并发现编码名称与uchardet
工具返回的名称不同(例如:uchardet
中的 x-mac-cyrillic 与iconv
中的 mac-cyrillic)
【讨论】:
【参考方案6】:enca 命令不适用于我的 GB2312 编码的简体中文文本文件。
相反,我使用以下函数为我转换文本文件。 您当然可以将输出重定向到文件中。
它需要 chardet 和 iconv 命令。
detection_cat ()
DET_OUT=$(chardet $1);
ENC=$(echo $DET_OUT | sed "s|^.*: \(.*\) (confid.*$|\1|");
iconv -f $ENC $1
【讨论】:
【参考方案7】:第一个答案
#!/bin/bash
find "<YOUR_FOLDER_PATH>" -name '*' -type f -exec grep -Iq . \; -print0 |
while IFS= read -r -d $'\0' LINE_FILE; do
CHARSET=$(uchardet $LINE_FILE)
echo "Converting ($CHARSET) $LINE_FILE"
# NOTE: Convert/reconvert to utf8. By Questor
iconv -f "$CHARSET" -t utf8 "$LINE_FILE" -o "$LINE_FILE"
# NOTE: Remove "BOM" if exists as it is unnecessary. By Questor
# [Refs.: https://***.com/a/2223926/3223785 ,
# https://***.com/a/45240995/3223785 ]
sed -i '1s/^\xEF\xBB\xBF//' "$LINE_FILE"
done
# [Refs.: https://justrocketscience.com/post/handle-encodings ,
# https://***.com/a/9612232/3223785 ,
# https://***.com/a/13659891/3223785 ]
进一步的问题:我不知道我的方法是否最安全。我这样说是因为我注意到某些文件没有正确转换(字符会丢失)或被“截断”。我怀疑这与“iconv”工具或使用“uchardet”工具获得的字符集信息有关。我对presented by @demofly 的解决方案很好奇,因为它可能更安全。
另一个答案
基于@demofly 的回答:
#!/bin/bash
find "<YOUR_FOLDER_PATH>" -name '*' -type f -exec grep -Iq . \; -print0 |
while IFS= read -r -d $'\0' LINE_FILE; do
CHARSET=$(uchardet $LINE_FILE)
REENCSED=`echo $CHARSET | sed 's#^x-mac-#mac#'`
echo "\"$CHARSET\" \"$LINE_FILE\""
# NOTE: Convert/reconvert to utf8. By Questor
recode $REENCSED..UTF-8 "$LINE_FILE" 2> STDERR_OP 1> STDOUT_OP
STDERR_OP=$(cat STDERR_OP)
rm -f STDERR_OP
if [ -n "$STDERR_OP" ] ; then
# NOTE: Convert/reconvert to utf8. By Questor
iconv -f "$CHARSET" -t utf8 "$LINE_FILE" -o "$LINE_FILE" 2> STDERR_OP 1> STDOUT_OP
STDERR_OP=$(cat STDERR_OP)
rm -f STDERR_OP
fi
# NOTE: Remove "BOM" if exists as it is unnecessary. By Questor
# [Refs.: https://***.com/a/2223926/3223785 ,
# https://***.com/a/45240995/3223785 ]
sed -i '1s/^\xEF\xBB\xBF//' "$LINE_FILE"
if [ -n "$STDERR_OP" ] ; then
echo "ERROR: \"$STDERR_OP\""
fi
STDOUT_OP=$(cat STDOUT_OP)
rm -f STDOUT_OP
if [ -n "$STDOUT_OP" ] ; then
echo "RESULT: \"$STDOUT_OP\""
fi
done
# [Refs.: https://justrocketscience.com/post/handle-encodings ,
# https://***.com/a/9612232/3223785 ,
# https://***.com/a/13659891/3223785 ]
第三个答案
带有 recode 和 vim 的混合解决方案:
#!/bin/bash
find "<YOUR_FOLDER_PATH>" -name '*' -type f -exec grep -Iq . \; -print0 |
while IFS= read -r -d $'\0' LINE_FILE; do
CHARSET=$(uchardet $LINE_FILE)
REENCSED=`echo $CHARSET | sed 's#^x-mac-#mac#'`
echo "\"$CHARSET\" \"$LINE_FILE\""
# NOTE: Convert/reconvert to utf8. By Questor
recode $REENCSED..UTF-8 "$LINE_FILE" 2> STDERR_OP 1> STDOUT_OP
STDERR_OP=$(cat STDERR_OP)
rm -f STDERR_OP
if [ -n "$STDERR_OP" ] ; then
# NOTE: Convert/reconvert to utf8. By Questor
bash -c "</dev/tty vim -u NONE +\"set binary | set noeol | set nobomb | set encoding=utf-8 | set fileencoding=utf-8 | wq\" \"$LINE_FILE\""
else
# NOTE: Remove "BOM" if exists as it is unnecessary. By Questor
# [Refs.: https://***.com/a/2223926/3223785 ,
# https://***.com/a/45240995/3223785 ]
sed -i '1s/^\xEF\xBB\xBF//' "$LINE_FILE"
fi
done
这是完美转化次数最多的解决方案。此外,我们没有任何截断的文件。
警告:备份您的文件并使用合并工具检查/比较更改。可能会出现问题! 提示:命令
sed -i '1s/^\xEF\xBB\xBF//' "$LINE_FILE"
可以在没有它的转换后与合并工具进行初步比较后执行,因为它会导致“差异”。
注意: 使用 find
进行搜索会从给定路径 ("") 及其子文件夹中找到所有非二进制文件。
【讨论】:
两个小提示:我会将<YOUR_FOLDER_PATH>
替换为"$1"
并让最终用户传入文件夹路径。而对于 MacOS 用户,您需要运行:brew install recode uchardet gnu-sed
,然后将 sed
更改为 gsed
以使其工作。使用grep -I
删除二进制文件做得很好。高分!
您的建议几乎被完全接受。我没有保留更改“我会将 iconv -f UTF-32 -t UTF-8 file.csv
***.com/questions/64860/…【参考方案8】:
使用 iconv 和 uchardet (谢谢 farseerfc)
鱼壳
cat your_file | iconv -f (uchardet your_file ) -t UTF-8
bash 外壳
cat your_file | iconv -f $(uchardet your_file ) -t UTF-8
如果使用 bash 脚本
#!/usr/bin/bash
for fn in "$@"
do
iconv < "$fn" -f $(uchardet "$fn") -t utf8
done
@flowinglight 在 ubuntu 组。
【讨论】:
以上是关于iconv 任何编码为 UTF-8的主要内容,如果未能解决你的问题,请参考以下文章