fileコマンド入門|拡張子に頼らずファイルの正体を知る

fileコマンド入門|拡張子に頼らずファイルの正体を知る

「.txt のはずなのに、開いたら画面が文字化けの砂嵐になった」

そんな場面に出くわしたこと、一度はあるのではないでしょうか。

拡張子は人間が付けたただのラベルにすぎません。

中身とラベルが食い違っていても、OS はとくに怒らないのです。

そこで頼りになるのが file コマンド。

この記事では、file を「中身の形式を見る」「表示を削る」「文字コードを見る」の3つに絞って整理しました。

手元の確認は Windows の Git Bash に同梱された file 5.46 で行っています。

fileは拡張子ではなく中身を読む

file が種類を判定する手がかりは、ファイルの先頭に置かれた数バイトの並び。

この目印はマジックナンバーと呼ばれ、PNG なら 89 50 4E 47、ZIP なら 50 4B のように形式ごとに決まっているのです。

つまりfile が見ているのはファイル名ではなく、中身の先頭

どれだけ拡張子を偽っても、中身のほうは嘘をつきません。

実際に、1×1 の PNG を notes.txt という名前でコピーして試してみました。

$ file notes.txt
notes.txt: PNG image data, 1 x 1, 8-bit/color RGBA, non-interlaced

拡張子が .txt でも、PNG だと即座に見抜いてくれます。

しかも画像サイズや色深度まで読み取ってくれるので、壊れているかどうかの当たりも付けやすいですね。

まず覚える3つ:そのまま・-b・-i

file の使い方は、この3つで大半の場面をしのげるはず。

1. そのまま渡す(種類を知る)

引数にファイルを並べるだけで、1行1ファイルの一覧が返ります。

$ file utf8.txt real.zip run.sh sub
utf8.txt: ASCII text
real.zip: Zip archive data, made by v2.0, extract using at least v2.0, ...
run.sh:   Bourne-Again shell script, ASCII text executable
sub:      directory

ディレクトリなら directory、シェルスクリプトなら先頭のシェバンまで読んで「Bourne-Again shell script」と答えてくれる親切さ。

なお、正体をつかめないバイナリは data という素っ気ない一語になります。

2. -b でファイル名を消す

スクリプトの中で結果を使うときは、行頭の「ファイル名:」がむしろ邪魔になりがち。

-b(brief)を付けると、判定結果だけが出力されます。

$ file -b tiny.png
PNG image data, 1 x 1, 8-bit/color RGBA, non-interlaced

条件分岐へ流し込む前処理としては、これがいちばん扱いやすい形なのです。

3. -i でMIMEタイプを見る

人間向けの説明文ではなく、機械で扱える形が欲しいときに使うのが -i です。

$ file -i tiny.png utf8ja.txt
tiny.png:   image/png; charset=binary
utf8ja.txt: text/plain; charset=utf-8

image/png のような MIME タイプなら、判定文字列がバージョンで揺れる心配も小さくなります。

形式だけが欲しいときは --mime-type を付けると、image/png の1語まで削れますよ。

文字コードの当たりを付ける

file の地味に嬉しい点が、テキストの文字コードまで一緒に見てくれるところ。

同じ「日本語のテキストです」を UTF-8 と Shift_JIS で保存し、並べて比べてみます。

$ file utf8ja.txt sjis.txt bom.csv
utf8ja.txt: Unicode text, UTF-8 text
sjis.txt:   Non-ISO extended-ASCII text
bom.csv:    Unicode text, UTF-8 (with BOM) text, with CRLF line terminators

UTF-8 は名指しで当ててくれる一方、Shift_JIS は「Non-ISO extended-ASCII text」という曖昧な答え。

日本語の文字コードを断定する用途には向いていない、と割り切っておくのが安全です。

それでも BOM の有無や改行コードまで教えてくれるので、文字化けの原因を絞り込む一手目としては十分に強力

3つ目の bom.csv では、BOM 付き UTF-8 であることと CRLF 改行であることが同時に読み取れています。

「開けない CSV」を渡されたとき、この1行だけで犯人の目星が付くこともあるのです。

文字コードそのものの仕組みは、別記事で整理しました。

文字化けはなぜ起きる?文字コード(UTF-8・Shift_JIS)とBOMの基礎

まとめて調べる・つまずきやすいところ

ディレクトリを丸ごと調べたいときは、find と組み合わせます。

file 自体に再帰オプションが無いので、ここは分業になるわけですね。

$ find . -type f -print0 | xargs -0 file | grep -i image
./notes.txt: PNG image data, 1 x 1, 8-bit/color RGBA, non-interlaced
./tiny.png:  PNG image data, 1 x 1, 8-bit/color RGBA, non-interlaced

grep で絞れば、「この中に画像が紛れていないか」を一発で洗い出せます

パイプで受け取りたいときは、ファイル名の代わりにハイフンを置くだけ。

$ cat tiny.png | file -
/dev/stdin: PNG image data, 1 x 1, 8-bit/color RGBA, non-interlaced

つまずきやすいのは、判定文字列が環境やバージョンによって微妙に変わる点でしょう。

スクリプトで分岐させるなら、説明文そのものではなく --mime-type の出力を条件にするほうが壊れにくいのです。

もう一歩踏み込んで、先頭のバイト列を自分の目で確かめたくなったら od や xxd の出番になります。

od・xxd入門|ファイルの中身をバイト単位で確かめる

逆に、ファイルではなくコマンドの正体を知りたい場面もあるはず。

which と type の違い|コマンドの正体を調べる

最後に

file は、拡張子という自己申告を疑うためのコマンドです。

そのまま渡して種類を知り、-b で表示を削り、-i で MIME を取り出す。

この3手を覚えておくだけで、「開く前にひとまず確かめる」という癖が身につきます。

正体不明のファイルを渡されたときこそ、まず file に一声かけてみてください

以上です。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA