オープンソースの画像生成AIをセットアップから使い方まで解説する『Stable Diffusion AI画像生成ガイドブック』(ソシム刊)発売中(→本のサポートページ

AutomatorでiPhoneの写真や画像のファイル名とタイムスタンプをいい感じにする

iOSを10にしたら、iPhoneMacにつないでもDropboxの「カメラアップロード」で「新しい写真/動画を見つけることができませんでした」しか言わなくなった。なぜ?

f:id:Imamura:20170803154258p:plain

理由はわからないがそういうことなら、別の方法で写真や画像を取り出すようにしよう。IFTTTを使うことにした。iPhoneにIFTTTを入れて(→[App Store])下のアプレットを検索し「Turn On」にする。

f:id:Imamura:20170801085219p:plain:h500

右上の歯車アイコンをタップして保存先のフォルダを選択。

f:id:Imamura:20170801085226p:plain:h500

写真を撮ったりスクリーンショットを取ったりしてしばらくたつと画像がDropboxへ転送され通知が出る。

f:id:Imamura:20170801085223p:plain:h500

おまけ情報
iPhoneのIFTTTではこのほか、「instagramへの投稿を写真つきでツイートする」というのを使っている。instagramへの投稿をTwitterに流してもタイムラインに写真が表示されないのはこれで解消できる→Tweet your Instagrams as native photos on Twitter - IFTTT https://ifttt.com/applets/103249p-tweet-your-instagrams-as-native-photos-on-twitter

さて、IFTTTを通して取得された画像のファイル名は「July_31__2017_at_0337PM.png」のような書式になる。ファイル名を日時にするとこの書式しか選べないようだ。Dropboxの「カメラアップロード」では「2017-07-31 15.37.48.png」という書式で保存されていた。iPhoneの写真や画像はこれの先頭に「iPhone_」をつけて「iPhone_2017-07-31 15.37.48.png」のようにしている。引き続きこういうファイル名を使っていきたい。

またDropboxへ転送されたファイルのタイムスタンプは撮影した日時ではなく転送された日時になってしまう。これもなんとかしたい。

Shupapanなどのリネームソフトを使うと、ファイル内の撮影情報をファイル名にしたり、ファイルのタイムスタンプを変えたりできる。

でもiPhoneから画像を転送するたびにこれを起動して操作するのは面倒だ。ドラッグ&ドロップすればファイル名やタイムスタンプが変更されるようなしくみにしたい。

そこでAutomatorを使うことにした。Automatorで「アプリケーション」を作ってそこへファイルをドラッグ&ドロップすればいろいろ処理される。

ファイル内の撮影情報を取得するには「ExifTool」や「Exiv2」を使う。

どちらも開発は活発で頼もしい。インストールはHomebrewが入っていればどちらも「install」一発で。

brew install exiftool
brew install exiv2

さて、ExifToolもExiv2も画像に埋め込まれた情報を取り出したり、それをもとにファイル名を変更したりできる。タイムスタンプの変更も可能だ。

ExifToolはリネーム時に重複するファイルがあると、ファイル名の末尾(拡張子の手前)に「-1」「-2」…と数字をつけてくれるオプションがある。HDR撮影(のオリジナルを残す設定)やバーストモードで撮影した写真は、撮影日時が秒まで同じになることがある。その対処もしてくれるなら今回はExifToolを使うことにしよう。

(Exiv2はExifToolより高速だそうなので、まったく同じ処理ならExiv2のほうがよいかも)

iPhoneスクリーンショットPNG形式で、これにも画像情報が含まれている。「DateCreated」というタグに画像の作成日時が入っているので、それをもとにファイル名やタイムスタンプを変更する。

写真の撮影日時を含むタグは「CreateDate」で、スクリーンショットとは異なる。画像にどちらのタグが含まれているかをチェックして処理を振り分けた。

以下のシェルスクリプトを使う。

#!/bin/bash
export PATH=${PATH}:/usr/local/bin/

for f in "$@"
do
	#撮影日時を含む写真にファイル名をつける
	if exiftool -s "${f}" | grep -q CreateDate ; then
		exiftool '-CreateDate>FileModifyDate' "${f}"
		exiftool '-FileName < CreateDate' -d iPhone_%Y-%m-%d\ %H.%M.%S%%-c.%%e "${f}"

	#撮影日時を含まずDateCreatedを含む画像にファイル名をつける
	elif exiftool -s "${f}" | grep -q DateCreated ; then
		XMP_CREATEDDATE=`exiftool -s "${f}" | grep -q DateCreated`
		YY=${XMP_CREATEDDATE:34:4}
		mm=${XMP_CREATEDDATE:39:2}
		DD=${XMP_CREATEDDATE:42:2}
		HH=${XMP_CREATEDDATE:45:2}
		MM=${XMP_CREATEDDATE:48:2}
		SS=${XMP_CREATEDDATE:51:2}
		EXT=${f##*.}
		NEWFILENAME="iPhone_$YY-$mm-$DD $HH.$MM.$SS.$EXT"
		TIMESTAMP="$YY$mm$DD$HH$MM.$SS"
		mv -f "${f}" "${f%/*}/$NEWFILENAME"
		touch -t $TIMESTAMP "${f%/*}/$NEWFILENAME"
	fi
done

上のシェルスクリプトの終わり近くにある「touch -t $TIMESTAMP "${f%/*}/$NEWFILENAME"」はシェルスクリプトのtouchコマンドでファイルのタイムスタンプを変更している。「touch -t 201708031234.56 ファイル名」でファイルのタイムスタンプが2017年8月3日12時34分56秒になる。

あとMacの「ターミナル」でファイルのタイムスタンプを秒まで見たいとき、lsコマンドの「--full-time」オプションは使えず、代わりに「-lT」(小文字のL+大文字のT)オプションを指定する。

Automatorとしてはこんな感じ。

f:id:Imamura:20170803155447p:plain

エラーが出る場合は改行を入れ直すといいかも
上のスクリプトをコピーしてもエラーが出て動かない場合、改行コードが原因かもしれない。Automatorのエディタ上ですべての改行を手で入れ直すと動くことがある。行頭にカーソルを持っていき[delete](backspace)を押してから[return]キーを押す。これをすべての行で行う。

「Finder項目をコピー」はスクリプトの信頼性が上がったら「Finder項目を移動」にしちゃってもいいし、そもそもIFTTTでコピー先のフォルダに直接転送してしまえば「Finder項目をコピー」のアクションは不要になる。

PNGやjpgの画像で、DateCreatedやCreateDateを含まなかった場合はリネームされない。Dropboxの画像転送で1枚だけ選択し、「次へ」をタップすると転送時のファイル名がわかる。これは「画像 2017-08-03 00.00.00.png」のような書式で、取得時(撮影時)のタイムスタンプになっている。これをもとに手動で「touch -t」コマンドを使っている。面倒だがやむをえない。

iPhoneで撮影した動画はどうしよう。動画はIFTTTでの自動転送はできないようなので、面倒だけれどiPhoneDropboxアプリで手動で転送しよう。

転送された動画のファイル名は「動画 2017-08-03 00.00.00.mov」という書式である。これをもとにファイル名とタイムスタンプを調整する。

作ったシェルスクリプトは以下。上と同様、Automatorで「アプリケーション」を作って「シェルスクリプトを実行」だけを使う。

for f in "$@"
do
	FILENAME=${f##*/}
	YY=${FILENAME:7:4}
	mm=${FILENAME:12:2}
	DD=${FILENAME:15:2}
	HH=${FILENAME:18:2}
	MM=${FILENAME:21:2}
	SS=${FILENAME:24:2}
	EXT=${f##*.}
	NEWFILENAME="iPhone_$YY-$mm-$DD $HH.$MM.$SS.$EXT"
	TIMESTAMP="$YY$mm$DD$HH$MM.$SS"
	cp "${f}" "${f%/*}/$NEWFILENAME"
	touch -t $TIMESTAMP "${f%/*}/$NEWFILENAME"
done

f:id:Imamura:20170803235745p:plain

これでよし。Dropboxで転送した画像は前述の通り「画像 2017-08-03 00.00.00.png」のようなファイル名になるので、これも上のシェルスクリプトを通していい感じにできる。

ExifToolで参考にしたページ

Exiv2で参考にしたページ

Exiv2で作ったシェルスクリプトは以下。JPGのリネームとタイムスタンプ変更が1行でできるのがExiftoolと違うところ。ただし重複チェックはできないようだ。

スクリプトが動かない理由が上記の改行コードの問題とわかるまでExifToolとExiv2を行ったり来たりしているうちExiv2でも動くコードができた)

#!/bin/bash
export PATH=${PATH}:/usr/local/bin #必要だった

for f in "$@"
do
	if exiv2 -Pk "${f}" | grep -q Exif.Photo.DateTimeOriginal ; then
		exiv2 -v -t -r "iPhone_%Y-%m-%d %H.%M.%S" "${f}"

    elif exiv2 -Pk "${f}" | grep -q Xmp.photoshop.DateCreated ; then
		XMP_CREATEDDATE=`exiv2 -PXt "${f}"`
		YY=${XMP_CREATEDDATE:0:4}
		mm=${XMP_CREATEDDATE:5:2}
		DD=${XMP_CREATEDDATE:8:2}
		HH=${XMP_CREATEDDATE:11:2}
		MM=${XMP_CREATEDDATE:14:2}
		SS=${XMP_CREATEDDATE:17:2}
		EXT=${f##*.}
		NEWFILENAME="iPhone_$YY-$mm-$DD $HH.$MM.$SS.$EXT"
		TIMESTAMP="$YY$mm$DD$HH$MM.$SS"
		mv -f "${f}" "${f%/*}/$NEWFILENAME"
		touch -t $TIMESTAMP "${f%/*}/$NEWFILENAME"
	fi
done

シェルスクリプトで参考にしたページ

※「${hoge/a/b}」は「最初のaのみbに置換」。すべてのaをbに置換したいときは「${hoge//a/b}」と書く。

pngファイルの重複チェック実装に参考になるかもしれないページ

参考

ファイルのタイムスタンプを撮影情報に合わせるアプリがあったが、自分のEl Capitanではうまく動作しなかった。

過去の関連記事

(2018年6月4日更新)