バイナリーデータの扱い方 - 拡張 POSIX シェルスクリプト Advent Calendar 2013 - ダメ出し Blog

2013-12-02(Mon) [sh][shell] [更新履歴]

拡張 POSIX シェルスクリプト Advent Calendar 2013、2日目の記事です。

シェルスクリプトによるバッチ処理は便利ですね! テキスト処理も、ちょっと勉強して頑張れば、sed や awk なしでも大抵のことはできます… そう、拡張 POSIX シェルである bash, ksh, zsh ならね。 しかし、シェルにとってバイナリーデータは苦手、というかそのままでは無理。 NULL とか、NULL とか、NULL とか…。

ところで先日、こんな blog を Twitter で見かけました。

「ほう…」と思い覗いてみたのですが、「『シェル芸』か?」という内容でした。 ふつうに外部のイメージ処理コマンド使っているじゃん! まあ、いいんですけどね。 人には言わない心の叫びです。気にしないでください。 外部コマンドとの華麗なコラボもシェルスクリプトの醍醐味の一つです。

後日、私と同じ感想を持った人がいて、それを受けて blog 記事が追加されました。

なるほどー。sed とか awk とか便利だよねー…って、これも「シェル芸」と言えるだろうか? 「芸」というと、もうちょっと、なんというか、その、あれ。 まあ、いいんですけどね。シェルももっと頑張れるんだー…っていうか、ね。

…というわけで、元ネタである 「JPEG ファイルから EXIF 等のアプリケーション付加情報を削除するシェルスクリプト」 を作ってみました。より「シェル芸」らしく、外部コマンドは od(1) だけを利用しています。bash, ksh, zsh で動きます。

jpeg-remove-appdata.bash

要は od -vtx1 でバイナリーデータをテキストデータに変換し、 テキストベースで処理、最後に printf (シェル組込みコマンド) でバイナリーに戻しているだけです。簡単ですね。 JPEG のデータフォーマットは今回始めて適当に調べて実装したので、 バグがあっても知りません。悪しからず。 エンディアンあたりが怪しいかも?

使用例:

$ ./jpeg-remove-appdata.bash src.jpg >dst.jpg

JPEG ファイル全体をテキスト化→バイナリー化するなどしているので、 はっきり言って遅いです。もっと効率的にやるなら、 dd(1) を利用して必要な部分だけ切り出すなどの工夫が必要。 ある JPEG ファイルで試してみたところ、bash 11秒、ksh 7秒、zsh 5秒でした。 やはり bash は遅い。


別解を見つけました。こちらはふつうの POSIX シェルで動きそうですね。 ざっと見たところ、EXIF の位置情報だけをクリアする実装のようです。 数少ない経験に依ると、アプリケーション (デジタルカメラ) 固有のタグ(?)に個人情報相当のデータが入っている場合があったような記憶が薄くあるのだけど、 そうだとすると、これでは不十分かな。


ところで、12月25日はクリスマスな上に、 OSS 界隈で地味に活躍されているふみやすさんの誕生日ですね!
http://www.amazon.co.jp/registry/wishlist/27M7TV8CEEF6G?sort=priority

逆に、あなたの書いた OSS や Blog や Advent Calendar が気に入ったら何か送りたく なってしまうかもしれないので、プロフィールや Web サイトに あなたの Amazon 欲しいものリストの URL を貼っておいてくださいね!


私が勤める OSSTech っていう某弊社で社員募集しているようです。 人材紹介会社を介さなければ、入社後に 20万円のボーナス! 「ふみやすっていう人に紹介された」と言ってもらえると私にもボーナス!! → https://www.osstech.co.jp/recruit/


よろしければ、これまで参加した/参加予定のほかの Advent Calendar もどうぞ。