BOM を含む UTF-8 ファイルを検索するエレガントな方法?
-
03-07-2019 - |
質問
デバッグの目的で、ディレクトリ内で UTF-8 バイト オーダー マーク (BOM) で始まるすべてのファイルを再帰的に検索する必要があります。私の現在の解決策は、単純なシェルスクリプトです。
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を検出するだけでなくクリアする1つの単純なコマンドについてはどうですか? :)
find . -type f -exec sed '1s/^\xEF\xBB\xBF//' -i {} \;
「見つける」が大好き:)
警告上記は、これら3文字を含むバイナリファイルを変更します。
。
BOMファイルのみを表示する場合は、これを使用します:
grep -rl \xEF\xBB\xBF' .
他のヒント
Windowsでこれを行うための最良かつ最も簡単な方法:
総司令官→プロジェクトのルートディレクトリに移動→ファイルの検索( Alt + F7 )→ファイルタイプ*。*→ 「EF BB BF」というテキストを検索→ [Hex]チェックボックスをオンにします→検索
そしてリストを取得します:)
find . -type f -print0 | xargs -0r awk '
/^\xEF\xBB\xBF/ {print FILENAME}
{nextfile}'
上記のソリューションのほとんどは、ファイル(Marcusのソリューションなど)が結果をフィルタリングしたとしても、ファイルの最初の行よりも多くテストします。このソリューションは、各ファイルの最初の行のみをテストするため、少し速くなるはずです。
いくつかの誤検知を受け入れた場合(非テキストファイルがある場合、またはまれにファイルの途中にZWNBSPがある場合)、grepを使用できます:
fgrep -rl `echo -ne '\xef\xbb\xbf'` .
次のようなものを使用します:
grep -orHbm1 "^`echo -ne '\xef\xbb\xbf'`" . | sed '/:0:/!d;s/:0:.*//'
BOMがファイルの最初のバイトから開始されるようにします。
grep
を使用してそれらを見つけ、Perlを使用してそれらを削除できます。
grep -rl \xEF\xBB\xBF' . | xargs perl -i -pe 's{\xEF\xBB\xBF}{}'
Windowsユーザーの場合は、 this ( BOM プロジェクト内のコード>)。
これに対する過剰な解決策は、 phptags
です(同じ名前のvi
ツール)、特にPHPスクリプトを探します:
phptags --warn ./
次のようなものを出力します:
./invalid.php: TRAILING whitespace ("?>\n")
./invalid.php: UTF-8 BOM alone ("\xEF\xBB\xBF")
そして、-whitespace
モードは、こうした問題を自動的に修正します(再帰的に、しかし.phpスクリプトのみを書き換えると断言します)。
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
正規表現に一致するファイルをリストします- 正規表現
^\xeff\xbb\xbf
これは完全に正しいわけではありません。行頭にゼロ幅のスペースがある場合、BOM のない UTF-8 ファイルと一致します。
これを使用してJavaScriptファイルのみを修正しました:
find . -iname *.js -type f -exec sed 's/^\xEF\xBB\xBF//' -i.bak {} \; -exec rm {}.bak \;
UTFファイルを探している場合、 fileコマンドが機能します。ファイルのエンコーディングが何であるかがわかります。 ASCII以外の文字が含まれている場合、UTFになります。
file *.php | grep UTF
しかし、それは再帰的に動作しません。おそらく、それを再帰的にするためにいくつかの派手なコマンドを作成できますが、レベルがなくなるまで、次のように各レベルを個別に検索しました。
file */*.php | grep UTF