gedit 无法识别字符编码,但 gvim 可以

Pet*_*r.O 5 gedit gvim ascii utf-8

我有很多来自 Windows 环境的纯文本文件。
他们中的许多人使用一个古怪的默认 Windows 代码页,它既不是 ASCII(7 位)也不是 UTF-8。

gvim打开这些文件没有问题,但gedit无法打开。
gvim报告编码为latin1

我假设gvim正在对代码页做出“聪明”的假设。
(我相信这个代码页仍然有国际变体)。

一些问题由此产生:

  • (1). 有什么方法可以告诉gedit识别这个代码页吗?
    **注意。[更新] 对于这一点 (1),请参阅下面的我的回答。
    ** 对于点 (2) 和 (3)。看到奥利的回答。

  • (2). 有没有办法扫描文件系统来识别这些问题文件?

  • (3). 是否有批量转换工具将这些文件转换为 UTF-8?

(.. 这个旧世界的文本混乱实际上是将我带到 Ubuntu 的最后一根稻草......默认情况下系统范围内的 UTF-8很棒

[更新]
**注: **我现在考虑下面的更新是部分无关紧要,因为“问题”文件不是“问题”(见下面的答案)。
我把它留在这里,因为它可能对某人有一些普遍的用处。


我已经制定了一个粗略和现成的方法来识别问题文件...
file命令不合适,因为它将我的示例文件识别为 ASCII...但 ASCII 文件 100% 符合 UTF-8...

正如我在下面的评论中提到的,对UTF-8 代码点的第一个字节无效的测试是:

  • 如果(UTF-8 代码点的)第一个字节在 0x80 和 0xBF 之间(为附加字节保留)或大于 0xF7(“超长格式”),则被视为错误

我知道sed(一个位,通过一个Win32端口),所以我设法凑齐其中发现这些正则表达式模式违规字节。

这是一条丑陋的线,所以如果正则表达式吓到你了,请立即移开视线:)

如果有人指出如何在范围 []表达式中使用十六进制值,我真的很感激。我刚刚使用了or运算符\|

fqfn="/my/fully/qualified/filename"  
sed -n "/\x80\|\x81\|\x82\|\x83\|\x84\|\x85\|\x86\|\x87\|\x88\|\x89\|\x8A\|\x8B\|\x8C\|\x8D\|\x8E\|\x8F\|\x90\|\x91\|\x92\|\x93\|\x94\|\x95\|\x96\|\x97\|\x98\|\x99\|\x9A\|\x9B\|\x9C\|\x9D\|\x9E\|\x9F\|\xA0\|\xA1\|\xA2\|\xA3\|\xA4\|\xA5\|\xA6\|\xA7\|\xA8\|\xA9\|\xAA\|\xAB\|\xAC\|\xAD\|\xAE\|\xAF\|\xB0\|\xB1\|\xB2\|\xB3\|\xB4\|\xB5\|\xB6\|\xB7\|\xB8\|\xB9\|\xBA\|\xBB\|\xBC\|\xBD\|\xBE\|\xBF\|\xF8\|\xF9\|\xFA\|\xFB\|\xFC\|\xFD\|\xFE\|\xFF/p" "${fqfn}"  
Run Code Online (Sandbox Code Playgroud)

所以,我现在将其移植到Oli 的批处理解决方案中...谢谢 Oli!

附注。这是它在我的示例文件中找到的无效 UTF-8 字节......
“H.Bork,Gøte-borg。” ... "ø" = F8 hex ... 这是一个无效的 UTF-8 字符。

Oli*_*Oli 4

iconv可能是您想要使用的。iconv -l将向您显示可用的编码,然后您可以使用几个命令对它们进行重新编码:

# all text files are in ./originals/
# new files will be written to ./newversions/

mkdir -p newversions
cd originals
for file in *.txt; do
    cat $file | iconv -f ASCII -t utf-8 > ../newversions/$file;
done
Run Code Online (Sandbox Code Playgroud)

如果您想对未编码的文件执行此操作(因为它们遍布各处),您需要引入更多命令:findfile和。最后两个只是用来处理文件的输出。awksed

for file in find . -type f -exec file --mime {} \; | grep "ascii" | awk '{print $1}' | sed s/.$//; do
    ...
Run Code Online (Sandbox Code Playgroud)

我不知道这是否真的有效,所以我当然不会从你拥有的最不重要的目录(创建一个包含一些已知 ASCII 文件的测试文件夹)之外的任何目录中运行它。find 的语法可能会阻止它进入 for 循环。我希望其他有更多 bash 经验的人可以跳进去并解决它,以便它做正确的事情。