シェルスクリプトの file
コマンドを利用する
file
コマンドを利用するといい感じでファイルタイプを判定してくれる。
オプションなしで実行
$ file a.sh b.png c.xml d.java e.jar
a.sh: Bourne-Again shell script text executable
b.png: PNG image data, 800 x 534, 8-bit/color RGB, non-interlaced
c.xml: XML document text
d.java: ASCII c program text
e.jar: Zip archive data, at least v1.0 to extract
--mime
オプションで mime-type 形式で出力してくれる。
--mimeオプションで実行
$ file --mime a.sh b.png c.xml d.java e.jar
a.sh: text/x-shellscript; charset=us-ascii
b.png: image/png; charset=binary
c.xml: application/xml; charset=us-ascii
d.java: text/x-c; charset=us-ascii
e.jar: application/zip; charset=binary
この出力に charset=binary
が含まれているかどうかをチェックするという方法。
check.sh
isBinary() {
a=$(file --mime "$1" | grep "charset=binary")
if [ -n "$a" ]; then return 0; fi
return 1
}
for f in a.sh b.png c.xml d.java e.jar; do
isBinary $f && echo $f is binary || echo $f is not binary
done
check.sh実行結果
$ sh check.sh
a.sh is not binary
b.png is binary
c.xml is not binary
d.java is not binary
e.jar is binary
参考リンク
- shell - How to check if the file is a binary file and read all the files which are not? - Stack Overflow
- Man page of FILE
Git 内部のバイナリ判定ロジックを利用する
Git では diff や merge でバイナリファイルかどうかを判定しており、その判定ロジックを利用しようという方法。
ただし内部の判定処理は明示的に公開されているものではないので、特定コマンドの出力結果パターンをチェックする。
check.sh
isBinary() {
p=$(printf '%s\t-\t' -)
t=$(git diff --no-index --numstat /dev/null "$1")
case "$t" in "$p"*) return 0 ;; esac
return 1
}
for f in a.sh b.png c.xml d.java e.jar; do
isBinary $f && echo $f is binary || echo $f is not binary
done
これで file
コマンドを利用した場合と同様な結果が得られる。
check.sh実行結果
$ sh check.sh
a.sh is not binary
b.png is binary
c.xml is not binary
d.java is not binary
e.jar is binary
git diff --numstat
で追加/削除の行数が出力されるが、バイナリの場合は行数とかカウントできないよね、ってことで以下のように出力結果パターンが変わることをチェックしているという。
$ git diff --no-index --numstat /dev/null a.sh
314 0 /dev/null => a.sh
$ git diff --no-index --numstat /dev/null b.png
- - /dev/null => b.png