如何在 Linux 上辨别文件名的语言编码?

如何在 Linux 上辨别文件名的语言编码?

我有一个目录,其中包含来自外部来源的大约 10,000 个图像文件。

许多文件名包含空格和标点符号,这些符号对数据库或网络都不太友好。我还想在每个文件名的末尾附加一个 SKU 编号(用于会计目的)。许多(如果不是大多数)文件名还包含扩展拉丁字符我想保留它为了 SEO 目的(具体来说,文件名准确地代表 Google 图片中的文件内容)

我编写了一个 bash 脚本,可以将所有文件重命名(复制)为我想要的结果。bash 脚本以 UTF-8 保存。运行后,它会忽略大约 500 个文件(无法统计文件...)。

我跑了convmv-f UTF-8-t UTF-8在目录中,发现这 500 个文件名是不是采用 UTF-8 编码(convmv 能够检测并忽略已经采用 UTF-8 编码的文件名)

有没有简单的方法可以让我找到哪个他们目前使用的语言编码?

我自己能找到的唯一方法是将终端编码设置为 UTF-8,然后使用 convmv 遍历所有可能的候选编码,直到显示“看起来正确”的转换名称。我无法确定这 500 个文件是否都使用相同的编码,因此我需要重复此过程 500 次。我想要一种比“看起来正确”更自动化的方法!!!

答案1

实际上,没有 100% 准确的方法,但有一种方法可以给出一个很好的猜测。

有一个 Python 库 chardet,可在此处使用:https://pypi.python.org/pypi/chardet

例如

查看当前 LANG 变量的设置:

$ echo $LANG
en_IE.UTF-8

创建需要使用 UTF-8 编码的文件名

$ touch mÉ.txt

更改我们的编码,看看当我们尝试列出它时会发生什么

$ ls m*
mÉ.txt
$ export LANG=C
$ ls m*
m??.txt

好的,现在我们有一个用 UTF-8 编码的文件名,并且我们当前的语言环境是 C(标准 Unix 代码页)。

因此,启动 python,导入 chardet 并让它读取文件名。我使用一些 shell 通配符(即通过 * 通配符扩展)来获取我的文件。将“ls m*”更改为与您的示例文件之一匹配的任何内容。

>>> import chardet
>>> import os
>>> chardet.detect(os.popen("ls m*").read())
{'confidence': 0.505, 'encoding': 'utf-8'}

如您所见,这只是一个猜测。“confidence”变量显示猜测的准确性。

答案2

您可能会发现这很有用,可以测试当前工作目录(python 2.7):

import chardet
import os  

for n in os.listdir('.'):
    print '%s => %s (%s)' % (n, chardet.detect(n)['encoding'], chardet.detect(n)['confidence'])

结果如下:

Vorlagen => ascii (1.0)
examples.desktop => ascii (1.0)
Öffentlich => ISO-8859-2 (0.755682154041)
Videos => ascii (1.0)
.bash_history => ascii (1.0)
Arbeitsfläche => EUC-KR (0.99)

要从当前目录递归路径,请将其剪切并粘贴到一个小的 Python 脚本中:

#!/usr/bin/python

import chardet
import os

for root, dirs, names in os.walk('.'):
    print root
    for n in names:
        print '%s => %s (%s)' % (n, chardet.detect(n)['encoding'], chardet.detect(n)['confidence'])

答案3

2021 年使用 python3 登陆这里时,我发现 @philip-reynoldsn @klaus-kappel 的答案很有用,但不再起作用,因为chardet.detect()需要一个字节类对象。我稍微编辑了代码以获取当前工作目录中所有文件的编码,如下所示:

import os
import chardet
for n in os.listdir('.'):
    chardet.detect(os.fsencode(n))

相关内容