使用BOM搜索UTF-8文件的优雅方式


Elegant way to search for UTF-8 files with BOM?

出于调试目的,我需要递归地在目录中搜索所有以UTF-8字节顺序标记(BOM)开头的文件。我目前的解决方案是一个简单的shell脚本:

find -type f |
while read file
do
    if [ "`head -c 3 -- "$file"`" == $''xef'xbb'xbf' ]
    then
        echo "found BOM in: $file"
    fi
done

或者,如果你喜欢简短的、不可读的单行:

find -type f|while read file;do [ "`head -c3 -- "$file"`" == $''xef'xbb'xbf' ] && echo "found BOM in: $file";done

它不适用于包含换行符的文件名,但是这样的文件无论如何都不是预期的。

有没有更短或更优雅的解决方案?

有什么有趣的文本编辑器或文本编辑器的宏吗?

这个简单的命令怎么办?它不仅能找到而且能清除讨厌的BOM?:)

find . -type f -exec sed '1s/^'xEF'xBB'xBF//' -i {} ';

我喜欢"寻找":)

警告以上内容将修改包含这三个字符的二进制文件。

如果您只想显示BOM文件,请使用以下文件:

grep -rl $''xEF'xBB'xBF' .

在Windows上做到这一点的最佳和最简单的方法:

总司令&rar;转到项目的根目录&rar;查找文件(Alt+F7)→文件类型*.*→查找文本"EF BB BF"&rar;选中"十六进制"复选框→搜索

您得到的列表是:)

find . -type f -print0 | xargs -0r awk '
    /^'xEF'xBB'xBF/ {print FILENAME}
    {nextfile}'

上面给出的大多数解决方案测试的内容都超过了文件的第一行,即使有些解决方案(如Marcus的解决方案)会过滤结果。这个解决方案只测试每个文件的第一行,所以应该会更快一些。

如果您接受一些假阳性(如果有非文本文件,或者在不太可能的情况下,文件中间有一个ZWNBSP),您可以使用grep:

fgrep -rl `echo -ne ''xef'xbb'xbf'` .

您可以使用grep来查找它们,并使用Perl来剥离它们,如下所示:

grep -rl $''xEF'xBB'xBF' . | xargs perl -i -pe 's{'xEF'xBB'xBF}{}'

我会使用这样的东西:

grep -orHbm1 "^`echo -ne ''xef'xbb'xbf'`" . | sed '/:0:/!d;s/:0:.*//'

这将确保BOM表从文件的第一个字节开始出现。

对于Windows用户,请参阅此(用于在项目中查找BOM的好PHP脚本)。

phptags(不是同名的vi工具)是一个过度使用的解决方案,它专门查找PHP脚本:

phptags --warn ./

将输出类似以下内容:

./invalid.php: TRAILING whitespace ("?>'n")
./invalid.php: UTF-8 BOM alone ("'xEF'xBB'xBF")

--whitespace模式将自动修复这些问题(递归地,但断言它只重写.php脚本。)

我只使用它来更正JavaScript文件:

find . -iname *.js -type f -exec sed 's/^'xEF'xBB'xBF//' -i.bak {} '; -exec rm {}.bak ';
find -type f -print0 | xargs -0 grep -l `printf '^'xef'xbb'xbf'` | sed 's/^/found BOM in: /'
  • find -print0在每个文件名之间加一个null ''0,而不是使用新行
  • xargs -0需要以null分隔的参数,而不是以行分隔的参数
  • grep -l列出了与正则表达式匹配的文件
  • regex ^'xeff'xbb'xbf并不完全正确,因为如果非BOMed UTF-8文件在一行的开头有零宽度空格,它将匹配这些文件

如果您正在查找UTF文件,file命令会起作用。它会告诉你文件的编码是什么。如果其中有任何非ASCII字符,它会显示UTF。

file *.php | grep UTF

不过,这不会递归地工作。您可能可以设置一些奇特的命令使其递归,但我只是像下面这样单独搜索每个级别,直到用完级别为止。

file */*.php | grep UTF