Linuxでスクリプトを介してファイルのエンコーディングを見つける方法は?


303

ディレクトリに配置されているすべてのファイルのエンコーディングを見つける必要があります。使用されているエンコーディングを見つける方法はありますか?

fileコマンドは、これを実行することはできません。

私にとって興味深いエンコーディングは、ISO-8859-1です。エンコードがそれ以外の場合は、ファイルを別のディレクトリに移動します。


1
使用したいスクリプト言語の種類がわかれば、質問にその言語の名前をタグ付けします。それが役立つかもしれません...
MatrixFrog 2009

1
または、おそらく彼はシェルスクリプトを作成しようとしているだけですか?
Shalom Craimer 2009

1
「どのスクリプト言語」に対する答えでしょう。
bignose 2009

7
おそらくこの回答とは関係ないかもしれませんが、一般的なヒント:疑問全体を1つの単語(ここでは「エンコーディング」)で説明できる場合は、だけを実行してくださいapropos encoding。すべてのマンページのタイトルと説明を検索します。私は私のマシン上でこれを行うと、私はその説明から判断すると、私を助けるかもしれない3つのツールを参照してくださいchardetchardet3chardetect3。次に、man chardetマンページを読んでみると、それchardetが必要なユーティリティであることがわかります。
John Red

1
ファイルの内容を変更すると、エンコーディングが変わる場合があります。例viで、単純なcプログラムを作成する場合、おそらくそうus-asciiですが、中国語のコメントを1行追加すると、になりutf-8ます。fileファイルの内容を読んで推測することで、エンコーディングを判別できます。
Eric Wang

回答:


419

あなたが探しているように聞こえますenca。エンコーディング間で推測したり変換したりすることもできます。ただ、見てmanページ

または、失敗した場合は、file -i(linux)またはfile -I(osx)を使用します。これにより、ファイルのMIMEタイプ情報が出力されます。これには、文字セットエンコーディングも含まれます。私もそれのマンページを見つけました:)


1
manページによると、ISO 8559セットについて知っています。多分少しおおざっぱに読んでみてください:-)
bignose

5
エンカは面白そうですね。残念ながら、検出は非常に言語に依存しているようで、サポートされている言語のセットはそれほど大きくありません。鉱山(de)がありません:-(とにかくクールなツールです
er4z0r 2010


6
enca英語で書かれたファイルの分析にはまったく役に立たないようですが、たまたまエストニア語で何かを見ていると、すべての問題が解決する可能性があります。非常に役立つツール、それ... </
sarcasm

6
@vladkras utf-8ファイルに非ASCII文字がない場合、asciiと区別できません:)
vadipp

85
file -bi <file name>

大量のファイルに対してこれを行う場合

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

ただし、ファイルがxmlファイルで、xml宣言に「encoding = 'iso-8859-1'」属性がある場合、ファイルコマンドは、真のエンコーディングがutf-8 ...
パー

6
なぜ-b引数を使用するのですか?file -i *だけを実行すると、すべてのファイルの推測された文字セットが出力されます。
Hans-PeterStörr2013年

4
-b引数についても興味がありました。manページには、「簡潔」を意味すると書かれていますDo not prepend filenames to output lines
craq

1
ファイル出力を解析する必要はfile -b --mime-encodingなく、文字セットエンコーディングのみを出力します
jesjimher

-bは 'be brief'を表します。これは基本的に、指定したファイル名を出力しないことを意味します。
ニコス

36

ウシャルデ -Mozillaから移植されたエンコード検出ライブラリ。

使用法:

~> uchardet file.java 
UTF-8

さまざまなLinuxディストリビューション(Debian / Ubuntu、OpenSuse-packmanなど)がバイナリを提供します。


1
ありがとう!さらに多くのパッケージに満足していませんsudo apt-get install uchardetが、とても簡単なので、心配する必要はありませんでした...
sage

上記のコメントで述べたように、uchardetはファイルのエンコードが「windows-1252」であると誤って通知しますが、そのファイルは明示的にUTF-8として保存しました。uchardetは、「自信を持って0.4641618497109827」とさえ言っていません。これにより、少なくとも完全なナンセンスなことを示しているというヒントが得られます。file、enca、encguessは正しく機能しました。
アルゴマン

uchardetだけではなく、ファイル全体(20GiBファイルで試しただけ)を分析するという点で、fileおよびencaに比べて大きな利点があります。
tuxayo

10

これは、ファイル-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

6
file -b --mime-encodingcharsetのみを出力するため、すべてのパイプ処理を回避できます
jesjimher

1
どうも。MacOSで指摘したように、これは機能しません。 ] file ... file -C -m magicfiles詳細については、 `file --help 'を試してください。
Wolfgang Fahl

6

それがiso-8859-1であるかどうかを判断することは本当に難しいです。7ビット文字のみのテキストで、iso-8859-1の場合もあるが、わからない場合。8ビット文字がある場合、上位領域の文字もエンコード順に存在します。そのため、辞書を使用して、どの単語であるかをより正確に推測し、そこからどの文字にする必要があるかを判断する必要があります。最後に、utf-8である可能性があることを検出した場合、iso-8859-1ではないと確信できます。

何も言われていないかわからないため、エンコーディングは最も難しい作業の1つです。


力ずくで攻撃しようとするのを助けるかもしれません。次のコマンドは、WINまたはISOで始まる名前のすべてのecncoding形式からUTF8への変換を試みます。次に、出力を手動でチェックして、正しいエンコーディングへの手掛かりを探す必要があります。もちろん、ISOまたはWINを適切なものに置き換えて、フィルターされたフォーマットを変更したり、grepコマンドを削除してフィルターを削除したりできます。for i for $(iconv -l | tail -n +2 | grep "(^ ISO \ | ^ WIN)" | sed -e 's / \ / \ ///'); $ iをエコーし​​ます。iconv -f $ i -t UTF8 santos; 完了。
ndvo

5

Debianでは次も使用できますencguess

$ encguess test.txt
test.txt  US-ASCII

uchardetUbuntu にインストールしたところ、ファイルはでしたWINDOWS-1252。これをテストするために、KateでUTF-16として保存したので、これは間違いでした。ただし、encguess正確に推測すると、Ubuntu 19.04にプリインストールされていました。
Nagev

5

エンコーディングを8859からASCIIに変換するには:

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

4

Pythonでは、chardetモジュールを使用できます:https : //github.com/chardet/chardet


存在しないドメイン:feedparser.org
Rune

このコメントの時点では、Github:github.com/dcramer/chardet
Rick Hanlon IIで

このコメントの時点では、githubのchardet / chardetにあります。回答を更新しました。
クエンティンプラデット2015年

chardetは "None"を報告します。chardet3は、私のPythonスクリプトが行うのとまったく同じ方法で、ファイルの最初の行をチョークします。
Joels Elf

3

これは、誰でもできる方法ではありません。一つの可能性は、それが範囲内の任意の文字が含まれていないことを確認するために、ファイル内のすべての文字を調べることであろう0x00 - 0x1fかを0x7f -0x9f私が言ったように、これはISO8859の少なくとも一つの他の変異体を含む、任意の数のファイルのための真のかもしれないが、。

別の可能性は、サポートされているすべての言語でファイル内の特定の単語を探し、それらを見つけることができるかどうかを確認することです。

したがって、たとえば、8859-1のサポートされているすべての言語で英語の「and」、「but」、「to」、「of」などに相当するものを見つけて、それらの中に多数の出現があるかどうかを確認します。ファイル。

私は次のような文字通りの翻訳について話しているのではありません:

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

それは可能ですが。私はターゲット言語の一般的な単語について話している(私が知っているすべてのことについて、アイスランド語には「および」の単語がない-おそらく「魚」にその単語を使用する必要があるだろう[申し訳ありませんが、少しステレオタイプで、私はしませんでした任意の違反を意味し、単なるポイントを説明します])。


2

より一般的な答えに興味があることはわかっていますが、ASCIIの優れた点は通常、他のエンコーディングでも優れています。以下は、標準入力がASCIIかどうかを判別するPythonの1行です。(私はこれが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

2

XMLファイル(ISO-8859-1)について話している場合、それらの内部のXML宣言はエンコードを指定します。<?xml version="1.0" encoding="ISO-8859-1" ?>
したがって、正規表現(たとえばperl)を使用して、そのような指定がないかすべてのファイルをチェックできます。
詳細については、「テキストファイルのエンコーディングを判別する方法」を参照してください。


その行は、使用しているエンコーディングがわからない人によってコピーアンドペーストされる可能性があります。
アルゴマン、

注意してください。冒頭の宣言については、ファイルが実際にそのようにエンコードされていることを保証するものは何もありません。あなたが本当に、本当に自分で検証するために必要なエンコーディングについて気にかけているのなら。
Jazzepi

2

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

0

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でサポートされているソースエンコーディングからすべてをutf8に変換できます。

例:

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

0

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


1
私が得る出力は、「通常のファイル」だけです
Mordechai

0

次のスクリプトを使用して

  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 {} \;

0

このコマンドで:

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

ディレクトリとサブディレクトリ内のすべてのファイルと対応するエンコーディングをリストできます。


-2

Perlでは、Encode :: Detectを使用します。


7
シェルでそれを使用する方法の例を挙げられますか?
Lri

別のポスター(@fccoelho)は、+ 3を取得するソリューションとしてPythonモジュールを提供し、このポスターは、Perlモジュールの場合を除いて、非常によく似た回答で-2を取得しました。なぜダブルスタンダードなのか!?
ハッピーグリーン

4
おそらく、perlワンライナーのコード例がこの答えを助けるでしょう。
vikingsteve 2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.