顧客から送られてきたファイルの拡張子がおかしくなっていたり、ファイルサーバに置いてあるファイルの拡張子が全部消えていたり……そういった場合に利用できる「file」というコマンドがある。頻繁に使うことはないと思うが、知っていると便利なので紹介しておこう。

ファイルの中身からデータを推測

例えば、以下のように拡張子が付いていないファイルがあったとする。

拡張子が付いていないので中身がよくわからないファイル

「less」や「more」などのページャで中身を確認しようとすると、次のようになった。

少なくともテキストファイルではなさそうだ

こうした場合に使えるコマンドが「file」だ。引数にファイルのパスを指定すると、次のように、そのファイルの中身からデータの種類を推測して表示してくれる。

$ file nazo*
nazo_01: JPEG image data, JFIF standard 1.01, aspect ratio, density 72x72, segment length 16, Exif Standard: [TIFF image data, big-endian, direntries=4, xresolution=62, yresolution=70, resolutionunit=2], baseline, precision 8, 953x634, frames 3
nazo_02: Algol 68 source, ASCII text
nazo_03: gzip compressed data, last modified: Fri Jul  7 08:47:47 2017, from Unix
nazo_04: ASCII text
$

ファイルの種類だけわかればよい場合には、-iオプションを指定して実行すればよい。次のように、ざっと種類を把握することができる。

$ file -i nazo*
nazo_01: image/jpeg; charset=binary
nazo_02: text/x-Algol68; charset=us-ascii
nazo_03: application/x-gzip; charset=binary
nazo_04: text/plain; charset=us-ascii
$

上から順にJPEG画像、Algol68ソースコード、GZIP圧縮ファイル、テキストファイルだ。

ちなみにfileコマンドのマニュアルには、fileコマンドのデフォルトの出力が人間にとって読みやすい表記で、-iオプションを指定したときにはmimeタイプで出力するとあるが、Web技術に精通したエンジニアが増えている現在では、どちらかというとmimeタイプのほうが簡潔でわかりやすいのではないかと思う。

さて、現在のところfileコマンドの使い方としてありそうなケースは、WebからダウンロードしてきたテキストファイルやHTMLファイルの文字コードを判断するようなときだろう。

先日Q-Successから発表されたデータによると、2017年10月13日の段階でWebページで使われている文字エンコーディングの90%はUTF-8だとされている(参考記事:Webサイトの文字コーディング、90%がUTF-8利用 - Shift JISは0.9%)。したがって、ほとんどの場合にはUTF-8を想定しておけばよいということになる。日本語の文字エンコーディングとしては、ほかに0.9%のShift JIS、0.3%のEUC-JPがあるそうなので、もしかするとこちらのエンコーディングに遭遇することもあるかもしれない。

fileコマンドは日本語の文字エンコーディングの判定は得意ではないが、UTF-8、Shift JIS、EUC-JPの判別であればfileコマンドでも実行できるので、裏技的にこの方法を覚えておくとよいかもしれない。UTF-8のindex_01.html、Shift JISのindex_02.html、EUC-JPのindex_03.htmlを用意してfileコマンドを実行すると次のような感じになる。

$ file index_0*
index_01.html: HTML document, UTF-8 Unicode text, with very long lines
index_02.html: HTML document, Non-ISO extended-ASCII text, with very long lines, with LF, NEL line terminators
index_03.html: HTML document, ISO-8859 text, with very long lines
$

ここでさらに、-iオプションを指定して出力させると次のようになる。

$ file -i index_0*
index_01.html: text/html; charset=utf-8
index_02.html: text/html; charset=unknown-8bit
index_03.html: text/html; charset=iso-8859-1
$

fileコマンドだとShift JISはunknown-8bitで検出され、EUC-JPはISO-8859-1として検出されることが多い。utf-8、unknown-8bit、iso-8859-1の出力が日本語が含まれているテキストの場合にはUTF-8、Shift JIS、EUC-JPになっていることが多いと覚えておくとよいだろう。

なお、文字エンコーディングを推測するコマンドはほかにも存在しており、そちらのほうが正確に結果を教えてくれる。頻繁にテキストファイルのエンコーディングを調べるのであれば、fileコマンドではなくそちらのコマンドを使うべきだということは最後に補説しておきたい。日本語の文字エンコーディングをfileコマンドで調べるのは、あくまでも裏技的なものだと思っておいてもらえればと思う。