根据file命令将文件转换为utf-8

根据file命令将文件转换为utf-8

有一个上传过程,读取文件并使用 sqlldr 将数据上传到数据库。我在 sqlldr 中处理文件时遇到无效号码问题。发现该文件是UTF-16格式,然后在notepad++中转换为UTF-8格式,它开始正常工作。现在我正在尝试系统地转换它,如下所示。

iconv -f UTF-16 -t UTF-8 file_name >output_file_name

该文件可能具有不同的编码,因此我想在转换之前找到该文件的编码,然后根据该编码进行转换。例如使用 file 命令仅从下面读取 UTF-16,然后在 -f 选项中使用它。

bash-4.2$ file "/FILE_UPLOADS/Relationship (4).txt"
/FILE_UPLOADS/Relationship (4).txt: Little-endian UTF-16 Unicode text, with CRLF line terminators

我怎么做?

答案1

vim能够自动检测一些文件编码并转换为 UTF-8,因此您可以尝试使用以下ex模式处理文件:

vim --clean -E -s -c 'argdo set fileencoding=utf-8 nobomb | update' -c q -- *.txt

我们update也只重写在此过程中修改过的文件。

答案2

您可以使用file -i,它将返回文件的 MIME 编码。

就像是:

iconv -f `file -i $file|grep -Po 'charset=\K.*'` -t UTF-8 $file > $file_converted

另一种方法是使用更专用的工具,例如:
https://gitlab.freedesktop.org/uchardet/uchardet
那么命令就变得更加简单了

iconv -f `uchardet $file` -t UTF-8 $file > $file_converted

但你需要安装它。

答案3

什么时候fileLittle-endian UTF-16 Unicode 文本或与--mime-encoding UTF-16LE,这意味着该文件以 UTF-16 编码,并带有 BOM,表明该文件采用小端字节序。

file无法检测没有 BOM 的 UTF-16 文本文件(小端或大端)。

对于 UTF-16 文本,它需要前两个字节为 0xff、0xfe(小端)或 0xfe 0xff(大端),然后检查前 64KiB 数据的其余部分是否像文本(仅查找文本文件中不需要的 UTF-16 编码的 ASCII 控制字符)。

为了iconvutf-16le表示小端 UTF-16没有BOM,而 utf-16 表示带有 BOM 的 utf-16,无论是大端还是小端。

所以如果你使用的输出file -b --mime-encoding作为charset in iconv,您最终会在输出中得到 UTF-8 编码的 BOM。

在这里,您可能想要类似的东西:

encoding=$(file -b --mime-encoding - < "$file") &&
  case $encoding in
    (utf-16[bl]e) iconv -f UTF-16 < "$file" -t UTF-8 > "$newfile";;
    (us-ascii | utf-8) ;; # already utf-8
    (*) printf >&2 '%s\n' "don't know what to do with a $encoding encoding"
  esac

如果这些是 Microsoft 文件(如 CRLF 所示),您可能需要dos2unix使用iconv. dos2unix(至少当前版本)应该能够检测 UTF-16 并转换为语言环境的字符集(LC_ALL=C.UTF-8 dos2unix如果您希望输出为 UTF-8,无论语言环境如何,请运行它)并将 CRLF 更改为 LF 并修复其他怪癖在微软的文件中。

相关内容