如何通过Linux上的脚本找到文件的编码?

我需要找到放在一个目录中的所有文件的编码。有没有办法找到所使用的编码?

file命令不能做到这一点。

我感兴趣的编码是ISO 8859 - 1。如果是其他编码,我想将文件移动到另一个目录。

623758 次浏览

听起来你在找enca。它可以猜测甚至在编码之间进行转换。只要看看手册页

否则,使用file -i (Linux)或file -I (OS X)。这将为文件输出mime类型的信息,其中还将包括字符集编码。我也为它找到了手册页:)

这不是一件万无一失的事情。一种可能是检查文件中的每个字符,以确保它不包含任何0x00 - 0x1f0x7f -0x9f范围内的字符,但正如我所说,这可能适用于任何数量的文件,包括至少一个ISO 8859的其他变体。

另一种可能是在文件中以所有支持的语言查找特定的单词,看看是否能找到它们。

因此,例如,找到英语“&;and", &;but", &;to", "of"等等,在ISO 8859-1支持的所有语言中,看看它们在文件中是否有大量的出现。

我说的不是直译,比如:

English   French
-------   ------
of        de, du
and       et
the       le, la, les

尽管这是可能的。我说的是目标语言中的常用词(据我所知,冰岛语中没有"and"-你可能不得不用他们的词来表示“鱼”。抱歉,这有点老套。我没有任何冒犯的意思,只是说明一个观点)。

真的很难确定它是否是ISO 8859-1。如果你有一个只有7位字符的文本,也可能是ISO 8859-1,但你不知道。如果你有8位字符,那么上区域字符也存在于顺序编码中。因此,你必须使用字典来更好地猜测它是哪个单词,并从中确定它必须是哪个字母。最后,如果您检测到它可能是UTF-8,那么您可以确定它不是ISO 8859-1。

编码是最难做的事情之一,因为你永远不知道是否没有任何东西告诉你。

在Python中,你可以使用chardet模块。

在Perl中,使用Encode::Detect。

如果你谈论的是XML文件(ISO-8859-1),其中的XML声明指定编码:<?xml version="1.0" encoding="ISO-8859-1" ?> 因此,您可以使用正则表达式(例如,使用Perl)来检查每个文件的这种规范

更多信息可以在这里找到:How to decide Text File Encoding .

我知道您对更一般的答案感兴趣,但是ASCII中的优点通常也适用于其他编码。下面是一个Python单行程序,用于确定标准输入是否是ASCII。(我很确定这在Python 2中可以工作,但我只在Python 3上测试过。)

python -c 'from sys import exit,stdin;exit()if 128>max(c for l in open(stdin.fileno(),"b") for c in l) else exit("Not ASCII")' < myfile.txt
file -bi <file name>

如果你喜欢对一堆文件这样做

for f in `find | egrep -v Eliminate`; do echo "$f" ' -- ' `file -bi "$f"` ; done

uchardet -从Mozilla移植的编码检测器库。

用法:

~> uchardet file.java
UTF-8

各种Linux发行版(DebianUbuntuopenSUSE吃豆子等)提供二进制文件。

下面是一个在Mac OS X上使用file -Iiconv的示例脚本。

对于你的问题,你需要使用mv而不是iconv:

#!/bin/bash
# 2016-02-08
# check encoding and convert files
for f in *.java
do
encoding=`file -I $f | cut -f 2 -d";" | cut -f 2 -d=`
case $encoding in
iso-8859-1)
iconv -f iso8859-1 -t utf-8 $f > $f.utf8
mv $f.utf8 $f
;;
esac
done

Cygwin中,这看起来对我有用:

find -type f -name "<FILENAME_GLOB>" | while read <VAR>; do (file -i "$<VAR>"); done

例子:

find -type f -name "*.txt" | while read file; do (file -i "$file"); done

你可以通过管道将其传输到AWK,并创建iconv命令将所有内容从iconv支持的任何源编码转换为UTF-8。

例子:

find -type f -name "*.txt" | while read file; do (file -i "$file"); done | awk -F[:=] '{print "iconv -f "$3" -t utf8 \""$1"\" > \""$1"_utf8\""}' | bash

在Debian中,你也可以使用:encguess:

$ encguess test.txt
test.txt  US-ASCII

由于它是一个perl脚本,它可以安装在大多数系统上,通过安装perl或脚本作为独立的,如果perl已经安装。

$ dpkg -S /usr/bin/encguess
perl: /usr/bin/encguess

您可以使用file命令提取单个文件的编码。我有一个sample.html文件:

$ file sample.html

HTML: HTML文档,UTF-8 Unicode文本,有很长的行

$ file -b sample.html

HTML文档,UTF-8 Unicode文本,有很长的行

$ file -bi sample.html

text / html;utf - 8字符集=

$ file -bi sample.html  | awk -F'=' '{print $2 }'

utf - 8

我正在使用以下脚本

  1. 找到所有匹配FILTER和SRC_ENCODING的文件
  2. 创建它们的备份
  3. 将它们转换为DST_ENCODING
  4. (可选)删除备份

 

#!/bin/bash -xe


SRC_ENCODING="iso-8859-1"
DST_ENCODING="utf-8"
FILTER="*.java"


echo "Find all files that match the encoding $SRC_ENCODING and filter $FILTER"
FOUND_FILES=$(find . -iname "$FILTER" -exec file -i {} \; | grep "$SRC_ENCODING" | grep -Eo '^.*\.java')


for FILE in $FOUND_FILES ; do
ORIGINAL_FILE="$FILE.$SRC_ENCODING.bkp"
echo "Backup original file to $ORIGINAL_FILE"
mv "$FILE" "$ORIGINAL_FILE"


echo "converting $FILE from $SRC_ENCODING to $DST_ENCODING"
iconv -f "$SRC_ENCODING" -t "$DST_ENCODING" "$ORIGINAL_FILE" -o "$FILE"
done


echo "Deleting backups"
find . -iname "*.$SRC_ENCODING.bkp" -exec rm {} \;

将ISO 8859-1编码转换为ASCII:

iconv -f ISO_8859-1 -t ASCII filename.txt

在PHP中,你可以像这样检查它:

显式指定编码列表:

php -r "echo 'probably : ' . mb_detect_encoding(file_get_contents('myfile.txt'), 'UTF-8, ASCII, JIS, EUC-JP, SJIS, iso-8859-1') . PHP_EOL;"

更准确的“mb_list_encodings"

php -r "echo 'probably : ' . mb_detect_encoding(file_get_contents('myfile.txt'), mb_list_encodings()) . PHP_EOL;"
在第一个例子中,您可以看到我使用了一个可能匹配的编码列表(检测列表顺序)。 为了得到更准确的结果,你可以使用所有可能的编码:< >强mb_list_encodings() < / >强

注意mb_*函数需要php-mbstring:

apt-get install php-mbstring

使用这个命令:

for f in `find .`; do echo `file -i "$f"`; done

您可以列出一个目录和子目录中的所有文件以及相应的编码。

如果文件名称中有空格,请使用:

IFS=$'\n'
for f in `find .`; do echo `file -i "$f"`; done

记住它会将当前Bash会话解释器更改为“space”。

我在一个需要跨平台支持的项目中工作,遇到了很多与文件编码相关的问题。

我做了这个脚本来转换所有的utf-8:

#!/bin/bash
## Retrieve the encoding of files and convert them
for f  `find "$1" -regextype posix-egrep -regex ".*\.(cpp|h)$"`; do
echo "file: $f"
## Reads the entire file and get the enconding
bytes_to_scan=$(wc -c < $f)
encoding=`file -b --mime-encoding -P bytes=$bytes_to_scan $f`
case $encoding in
iso-8859-1 | euc-kr)
iconv -f euc-kr -t utf-8 $f > $f.utf8
mv $f.utf8 $f
;;
esac
done

我使用了一个黑客来读取整个文件,并使用file -b --mime-encoding -P bytes=$bytes_to_scan $f估计文件编码