答案1
尽管您要求查找 BOM,但使用file
甚至可能在不存在此类 BOM 时给出结果。来自man file
:
如果文件与魔法文件中的任何条目都不匹配,则将检查该文件是否为文本文件。ASCII、ISO-8859-x、非 ISO 8 位扩展 ASCII 字符集(例如 Macintosh 和 IBM PC 系统上使用的字符集)、UTF-8 编码的 Unicode、UTF-16 编码的 Unicode 和 EBCDIC 字符集可以通过构成每个集合中可打印文本的不同字节范围和序列来区分。如果文件通过了其中任何一项测试,则会报告其字符集。
因此,例如:
查找 . -type f -exec file --mime {} \; | grep "charset=utf-16"
答案2
您可以使用grep
:
grep -rl $(echo -ne '^\0376\0377') *
(已使用bash
GNU grep 测试,可能与其他版本兼容。)
解释:
$(echo... 部分生成 BOM(十六进制 FE FF,作为八进制转义序列),然后将其grep
作为其模式输入,并在前面加上 '^'(=匹配行首)。
-r 是递归搜索,-l 使 grep 打印它找到的文件的名称(而不是匹配的行)。
这可能有点浪费,因为 grep 会彻底扫描每个文件,而不仅仅是开始部分。如果主要是小文本文件,那就无所谓了。如果你有大量几 MB 的文件,你就必须编写一个 perl 脚本 :-)。
或者,您可以尝试file
(结合 find+xargs)。file
将识别 UTF-16(作为“UTF-16 Unicode 字符数据”)。但是,我不知道它有多可靠(因为它使用启发式方法)。
答案3
这是我用来查找 UTF-16 文件并随后将它们转换为 UTF-8 的脚本。#!/bin/sh
find ./ -type f |
while read file; do
if [ "`head -c 2 -- "$file"`" == $'\xff\xfe' ]
then
echo "Problems with: $file"
# If you want to convert to UTF-8 uncomment these lines.
#cat "$file" | iconv -f UTF-16 -t UTF-8 > "$file.tmp"
#mv -f "$file.tmp" "$file"
fi
done
答案4
感谢大家的帮助。在我的 Mac 上效果最好的是:
find . -type f -exec awk -F '\n' '/^\xFE\xFF|\xFF\xFE/ { print FILENAME; nextfile } { nextfile }' {} \;
它基于 sleske 的解决方案,但考虑到字节顺序标记可以反转。它还使用 awk 在第一行之后停止查找 BOM,因为 BOM 必须位于文件的开头。用于指定 BOM 的 \x 转义适用于 bash,我不知道它是否适用于其他 shell。
ghostdog74 建议的 enca 工具也可以完成这项工作,但我的 Mac 上没有这个工具。