Exif情報を削除するサービスメニューにする

前回の日記で、画像のexif情報を操作するexiftoolコマンドを覚えた。それにしてもexiftoolコマンドはかなり多機能で、オプションの設定次第で相当高度な機能も引き出せそう。まだ全然使いこなせてはいないが、少しずつ使い方が分かってきた。しかし、GUI操作が基本の自分にとって、せっかく覚えたオプション指定もいずれ忘れてしまいそう...。たぶん、毎回オプションを調べ直して使う羽目になる。そうならないように、よく使いそうな機能に絞り込んで、サービスメニューに登録しておくことにした。

exiftoolコマンドの使い方を探る

サービスメニューに登録する前に、もう少し便利に使えそうなオプション指定を調べてみた。

  • すべてのExif情報を削除する。
    • 元ファイル~/Desktop/IMG_0439.JPGは、~/Desktop/IMG_0439.JPG_originalに名所変更してバックアップする。
    • Exif情報を削除したファイルは、~/Desktop/IMG_0439.JPGとして保存される。
$ exiftool -all= ~/Desktop/IMG_0439.JPG
  • ちなみに、ExifGPS情報のみ削除するには、-geotagオプションに変更する。
$ exiftool -geotag= ~/Desktop/IMG_0439.JPG
  • 元ファイルをバックアップせず上書きする場合は、-overwrite_originalオプションを追記する。
$ exiftool -all= -overwrite_original ~/Desktop/IMG_0439.JPG
  • 出力するファイル名を指定したい場合は、-oオプションを追記する。
  • -oオプションの引数に指定した文字列がファイル名になる。
  • -oオプションの引数にフォーマット文字列を指定すれば、元ファイル名をルールに従って変更できる。
    • %d...元ファイルまでのディレクトリを出力する。
    • %f...元ファイルの名前(拡張子なし)を出力する。
    • %e...元ファイルの拡張子(.を含まない)を出力する。
    • %c...ファイル名が重複していた場合、重複しなくなるまで1、2、3...とカウントアップした数字を出力する。
$ exiftool -all= -o %dno_exif%+c_%f.%e ~/Desktop/IMG_0439.JPG
  • 上記で~/Desktop/no_exif_IMG_0439.JPG、あるいは重複すれば~/Desktop/no_exif_1_IMG_0439.JPGに出力される。
  • 数字の部分は必要に応じて2、3...と、重複しないファイル名になるまで変化する。
  • ちなみに、%cのバリエーションはかなり豊富。
 -o A%-cZ.txt      # AZ.txt, A-1Z.txt, A-2Z.txt ...
 -o B%5c.txt       # B.txt, B00001.txt, B00002.txt ...
 -o C%.c.txt       # C0.txt, C1.txt, C2.txt ...
 -o D%-.c.txt      # D-0.txt, D-1.txt, D-2.txt ...
 -o E%-.4c.txt     # E-0000.txt, E-0001.txt, E-0002.txt ...
 -o F%-.4nc.txt    # F-0001.txt, F-0002.txt, F-0003.txt ...
 -o G%+c.txt       # G.txt, G_1.txt G_2.txt ...
 -o H%-lc.txt      # H.txt, H-b.txt, H-c.txt ...


この設定で良さそうな気がしたが、一つ問題が発生。

  • すべてのExif情報を削除してしまうと、画像の方向も無視されて、変な向きの画像になってしまう場合があるのだ。
  • 画像の方向だけは保持したい。以下のようにしてみた。
n=`/usr/bin/exiftool -b -orientation ~/Desktop/IMG_0439.JPG`
/usr/bin/exiftool -all= -orientation#=$n -o %dno_exif%+c_%f.%e ~/Desktop/IMG_0439.JPG

AppleScriptにまとめる

上記コードをAppleScriptから呼び出すようにして、確認ダイアログや完了メッセージと組み合わせて以下のようにしてみた。


on run {input, parameters} set msg to (input's number as text) & "件のファイルから、すべてのExif情報を削除します。"
activate
display dialog msg buttons {"キャンセル", "上書き", "別名で保存"} default button "キャンセル" with icon 2
set button_pressed to result's button returned
set pathList to {} repeat with aFile in input
set aUNIXPath to (aFile as text)'s POSIX path
--do shell script "/usr/bin/exiftool -all= " & aUNIXPath
--元ファイル名.拡張子_originalにバックアップされる
if button_pressed is "上書き" then
--上書き保存する
do shell script "n=`/usr/bin/exiftool -b -orientation " & aUNIXPath & "`; /usr/bin/exiftool -all= -orientation#=$n -overwrite_original " & aUNIXPath
set pathList's end to aUNIXPath & return
else
--no_geotag_カウント数_元ファイル名.拡張子で保存する
do shell script "n=`/usr/bin/exiftool -b -orientation " & aUNIXPath & "`; /usr/bin/exiftool -all= -orientation#=$n -o %dno_exif%+c_%f.%e " & aUNIXPath
set pathList's end to "no_exif#_" & my fileName(aUNIXPath) & return
end if
end repeat
do shell script "/usr/local/bin/growlnotify 'すべてのExif情報を削除しました。' -m " & pathList as text
return input
end run

on fileName(unixPath) tell application "Finder"
(POSIX file unixPath as alias)'s name
end tell
end fileName

Automatorに組み込んでサービスにする

  • ワークフローのテンプレートにサービスを選択。
  • "サービス"は次の選択項目を受け取ります:イメージファイル
  • 検索対象:Finder.app


  • Automatorの保存を完了すると、サービスメニューに追加された!


シェルスクリプト

name_text=""
for fpath in "$@"
do
	n=`/usr/bin/exiftool -b -orientation "$fpath"`
	/usr/bin/exiftool -all= -orientation#=$n -o %dno_exif%+c_%f.%e "$fpath"

	# fname="${fpath##*/}"       /* ファイル名 */
	# fname_no_ext="${fname%.*}" /* ファイル名(拡張子なし) */
	# fdir="${fpath%/*}"         /* ディレクトリ */
	# fext="${fpath##*.}"        /* 拡張子(.を含まない) */
	fname="${fpath##*/}"
	name_text="${name_text}no_exif_#_${fname}\n"
done
echo -e "$name_text"|/usr/local/bin/growlnotify "すべてのExif情報を削除しました。"
  • 引数は$@で取得できる。(入力の引き渡し方法:引数として を選択した場合)
    • OSXはファイル名に半角スペースが多用されるので、クォートで囲んで"$@"とした。
    • 選択アイテムのパスが、テキストで取得できた。
  • オートメーターに組み込むと、以下のようになった。



以上で、すべてのExif情報を削除する(但し画像の方向だけは残す)サービスメニューの出来上がり。

追記

  • パスからファイル名とディレクトリを分離するには、basename・dirnameコマンドも便利だった。
$ basename /a/b/c.txt
c.txt

$ basename /a/b/c.txt .txt
c

$ dirname /a/b/c.txt
/a/b