スクリプトを使用してUnixでファイルのエンコーディングを見つける方法
質問
ディレクトリに配置されているすべてのファイルのエンコーディングを見つける必要があります。使用されているエンコーディングを見つける方法はありますか?
file
コマンドではこれができません。
私にとって興味深いエンコーディングは、ISO-8859-1です。エンコーディングがそれ以外の場合、ファイルを別のディレクトリに移動します。
他のヒント
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ディストリビューション(Debian / Ubuntu、OpenSuse-packmanなど)がバイナリを提供しています。
これは、ファイル-Iおよびiconvを使用してMacOsXで動作するスクリプトの例です 質問には、iconvの代わりにmvを使用する必要があります
#!/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
iso-8859-1かどうかを判断するのは非常に困難です。 iso-8859-1である可能性のある7ビット文字のみのテキストがある場合、それはわかりません。 8ビット文字を使用している場合、上位領域の文字も順番にエンコードされています。そのため、辞書を使用して、どの単語であるかをより正確に推測し、そこからどの文字であるかを判断する必要があります。最後に、utf-8である可能性があることを検出した場合、iso-8859-1ではないことを確認します
エンコーディングは、何も伝えていないかわからないため、最も難しいことの1つです
Pythonでは、chardetモジュールを使用できます。 https://github.com/chardet/chardet
Debianでは以下も使用できます:encguess
:
$ encguess test.txt
test.txt US-ASCII
これは、絶対確実にできる方法ではありません。 1つの可能性は、ファイル内のすべての文字を調べて、0x00 - 0x1f
または0x7f -0x9f
の範囲の文字が含まれていないことを確認することですが、前述したように、これは少なくともISO8859のもう1つのバリアント。
別の可能性は、サポートされているすべての言語でファイル内の特定の単語を探し、それらを見つけることができるかどうかを確認することです。
したがって、たとえば、英語の<!> quot; and <!> quot;、<!> quot; but <!> quot;、<!> quot; to <!> quot ;、 <!> quot; of <!> quot; 8859-1のサポートされているすべての言語で同様に実行し、ファイル内に多数の出現があるかどうかを確認します。
次のような文字通りの翻訳については話していない:
English French
------- ------
of de, du
and et
the le, la, les
それは可能ですが。ターゲット言語の一般的な単語について話している(私が知っている限り、アイスランド語には<!> quot; and <!> quot;の単語はありません-<!> quot; fishの単語を使用する必要があります<!> quot; [ちょっとステレオタイプなのはごめん、私は攻撃を意味するものではなく、ポイントを示すだけです])
XMLファイル(ISO-8859-1)について話している場合、その内部のXML宣言はエンコードを指定します:<?xml version="1.0" encoding="ISO-8859-1" ?>
そのため、正規表現(たとえばperl
を使用)を使用して、そのような仕様のすべてのファイルをチェックできます。
詳細については、テキストファイルのエンコーディングを決定する方法。
エンコーディングを8859からASCIIに変換するには:
iconv -f ISO_8859-1 -t ASCII filename.txt
より一般的な答えに興味があることは承知していますが、ASCIIの長所は通常、他のエンコーディングにも有効です。以下は、標準入力がASCIIかどうかを判断するためのPythonワンライナーです。 (これは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
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でサポートされているソースエンコーディングからすべてをutf8に変換するiconvコマンドを作成できます。
例:
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
fileコマンドを使用して、単一ファイルのエンコーディングを抽出できます。 sample.htmlファイルには次のものがあります。
$ file sample.html
sample.html:HTMLドキュメント、UTF-8 Unicodeテキスト、非常に長い行
$ file -b sample.html
HTMLドキュメント、UTF-8 Unicodeテキスト、非常に長い行
$ file -bi sample.html
text / html; charset = utf-8
$ file -bi sample.html | awk -F'=' '{print $2 }'
utf-8
次のスクリプトを使用して
- FILTERがSRC_ENCODINGに一致するすべてのファイルを見つける
- それらのバックアップを作成
- それらをDST_ENCODINGに変換する
- (オプション)バックアップを削除します
。
#!/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 {} \;
Perlでは、Encode :: Detectを使用します。