将任何编码转换为 UTF-8

问题描述 投票:0回答:8

我尝试将 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
linux ubuntu encoding utf-8 iconv
8个回答
22
投票

也许您正在寻找

enca
:

Enca 是一个极其简单的字符集分析器。它检测文本文件的字符集和编码,还可以使用内置转换器或外部库和工具(如 libiconv、librecode 或 cstocs)将它们转换为其他编码。

目前它支持白俄罗斯语、保加利亚语、克罗地亚语、捷克语、爱沙尼亚语、匈牙利语、拉脱维亚语、立陶宛语、波兰语、俄语、斯洛伐克语、斯洛文尼亚语、乌克兰语、中文以及一些独立于语言的多字节编码。

请注意,一般来说,自动检测当前编码是一个困难的过程(相同的字节序列可以是多种编码中的正确文本)。

enca
根据您告诉它要检测的语言使用启发式方法(以限制编码数量)。您可以使用
enconv
将文本文件转换为单一编码。


14
投票
您可以使用标准 gnu utils 文件和 awk 获得您需要的内容。示例:

file -bi .xsession-errors

给我:
“文本/纯文本;字符集=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
    

7
投票
这是

我的解决方案,使用recodeuchardet来放置所有文件:

#!/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 编码的解决方法。
许多不常见的编码需要像这样的解决方法。


5
投票
将它们全部编译。转到目录,创建

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
    

2
投票
第一个回答

#!/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://stackoverflow.com/a/2223926/3223785 , # https://stackoverflow.com/a/45240995/3223785 ] sed -i '1s/^\xEF\xBB\xBF//' "$LINE_FILE" done # [Refs.: https://justrocketscience.com/post/handle-encodings , # https://stackoverflow.com/a/9612232/3223785 , # https://stackoverflow.com/a/13659891/3223785 ]

进一步的问题:我不知道我的方法是否最安全。我这样说是因为我注意到某些文件未正确转换(字符将丢失)或被“截断”。我怀疑这与“iconv”工具或使用“uchardet”工具获得的字符集信息有关。我对@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://stackoverflow.com/a/2223926/3223785 , # https://stackoverflow.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://stackoverflow.com/a/9612232/3223785 , # https://stackoverflow.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://stackoverflow.com/a/2223926/3223785 , # https://stackoverflow.com/a/45240995/3223785 ] sed -i '1s/^\xEF\xBB\xBF//' "$LINE_FILE" fi done

这是完美转化次数最多的解决方案
。此外,我们没有任何被截断的文件。


警告:
    备份文件并使用合并工具检查/比较更改。可能会出现问题!
  • 提示:
  • 命令
  • sed -i '1s/^\xEF\xBB\xBF//' "$LINE_FILE"可以在没有合并工具的转换后与合并工具进行初步比较后执行,因为它可能会导致“差异”。
    注意:
  • 使用
  • find 进行搜索会带来给定路径 ("") 及其子文件夹中的所有非二进制文件。
        
使用 iconv 和 uchardet (thx farseerfc)

2
投票
鱼壳

cat your_file | iconv -f (uchardet your_file ) -t UTF-8

bash shell
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

作者:ubuntu 小组的@flowinglight。
    

查看 Linux cli 中可用于数据转换的工具:

0
投票

此外,还需要找到 iconv

中可用的编码的完整列表。只需运行

iconv --list

 即可发现编码名称与 
uchardet
 工具返回的名称不同(例如:
uchardet
 中的 x-mac-cyrillic 与 
iconv
 中的 mac-cyrillic)

enca 命令不适用于我的 GB2312 编码的简体中文文本文件。

0
投票
相反,我使用以下函数来转换文本文件。 您当然可以将输出重定向到文件中。

它需要

chardet

iconv 命令。 detection_cat () { DET_OUT=$(chardet $1); ENC=$(echo $DET_OUT | sed "s|^.*: \(.*\) (confid.*$|\1|"); iconv -f $ENC $1 }


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