iPhoneの複数画像・動画を正しい撮影日で一括リネームするバッチ

iPhone内の画像や動画のファイル名を日付時刻にしたかった。Windows標準の作成日時(%~z)では不正確だったため、画像にはImageMagick、動画にはffprobe(ffmpeg)を用いる。

更新情報

180219:ブログタイトルを変更、画像リネームバッチにおいてExifが無かった場合の処理にバグがあったので修正、iphone用一括処理バッチを追加

ImageMagickで画像ファイルの日付時刻リネーム

環境構築

https://www.imagemagick.org/script/download.php#windowsからImagemagickをDL。インストーラを実行。
・Q8、Q16:16ビットカラーの画像を正しく扱うためQ16、ただしリソースを食うので注意
・HDRI:必要ない
x86、x64:OSのアーキテクチャに合わせる

バッチ

画像の入ったフォルダをD&Dで動作する。

@echo off
rem 連番がつく、ImageMagickを使うので撮影日時でリネーム出来るやつ。Exif情報を含む画像のみ動画非対応。
echo %1内のファイルをExifからリネーム中…
cd /d %1
for %%a in ( *.* ) do (
    call :sub "%%a"
)
pause
exit

:sub
echo %1
rem ImageMagickのidentifyコマンドを使ってexif:DateTimeOriginalを出力し環境変数Exifに設定
rem magick identify -verbose %1 > Exif.txt で詳細出力可能
rem for /f "delims=" %%i in ('findstr "exif:DateTimeOriginal" "Exif.txt"') do (set EXIF=%%i)
for /f "delims=" %%a in ('magick identify -format "%%[exif:DateTimeOriginal]" %1') do (
    set "EXIF=%%a"
)
if not defined "%EXIF%" (
    call :noexif %1
)
rem %EXIF% "2017:12:18 12:53:24 "->"171218_1253"
set EXIF=%EXIF:~2,2%%EXIF:~5,2%%EXIF:~8,2%_%EXIF:~11,2%%EXIF:~14,2%
if not exist %EXIF%%~x1 (
    ren %1 %EXIF%%~x1
) else if exist %EXIF%%~x1 (
    set cnt=0
    :loop
    set /a cnt=cnt+1
    if not exist %EXIF%_%cnt%%~x1 (
        ren %1 %EXIF%_%cnt%%~x1
    ) else if exist %EXIF%_%cnt%%~x1 (
        goto :loop
    )
)
exit /b

:noexif
for /f "delims=" %%a in ('magick identify -format "%%[date:modify]" %1') do (
    set EXIF=%%a
)
exit /b

ffprobeで動画ファイルの日付時刻リネーム

環境構築

https://ffmpeg.zeranoe.com/builds/からffmpegをDL。環境変数Pathに登録する。
・Version:Release builds(安定版)推奨
・Architecture:OSのアーキテクチャに合わせる
・Linking:Shared(dll)推奨

バッチ

動画の入ったフォルダをD&Dで動作する。

@echo off
rem 連番がつく、ffprobeを使うので撮影日時でリネーム出来るやつ。iphoneで撮った動画のみ?対応画像非対応。
echo %1内のファイルをExifからリネーム中…
for %%a in ("%~1\*.*") do (
    call :sub "%%a"
)
pause
exit

:sub
echo %1
rem ffprobeの-show_entriesスイッチを使ってformat_tags=com.apple.quicktime.creationdateを出力し環境変数Exifに設定
rem format_tags=creation_timeは世界標準時
for /f "delims=" %%a in ('ffprobe -v quiet -i %1 -show_entries format_tags^=com.apple.quicktime.creationdate -of default^=noprint_wrappers^=1:nokey^=1') do (
    set "EXIF=%%a"
)

rem %EXIF% "2018-01-26T19:07:41+0900"->"180126_1907"
set EXIF=%EXIF:~2,2%%EXIF:~5,2%%EXIF:~8,2%_%EXIF:~11,2%%EXIF:~14,2%
echo %EXIF%
if not exist %EXIF%%~x1 (
    ren %1 %EXIF%%~x1
) else if exist %EXIF%%~x1 (
    set cnt=0
    :loop
    set /a cnt=cnt+1
    if not exist %EXIF%_%cnt%%~x1 (
        ren %1 %EXIF%_%cnt%%~x1
    ) else if exist %EXIF%_%cnt%%~x1 (
        goto :loop
    )
)
exit /b

nyanshiba.hatenablog.com

面倒なので一括処理

大まかな流れ
1. AAEファイルを削除
2. jpgをExifからリネーム
3. pngをメタデータからリネーム
4. pngをjpgに変換
5. pngを削除
6. movをメタデータからリネーム
7. mp4をメタデータからリネーム
終了
@echo off
rem D&Dしたフォルダをカレントディレクトリに
cd /d %1
echo 処理フォルダ:%1
rem AAEファイルを削除
del *.AAE
echo AAEを削除


rem ==========画像を日付リネーム==========
echo jpgをExifからリネーム
for %%a in ( *.jpg ) do (
    call :subimage "%%a"
)
echo pngをメタデータからリネーム
for %%a in ( *.png ) do (
    call :subimage "%%a"
)


rem ==========PNGをJPGに変換してPNGを削除==========
echo pngをjpgに変換
for %%a in ( *.png ) do (
    call :subpngjpg "%%a"
)
del *.png
echo pngを削除


rem ==========動画を日付リネーム==========
echo movをメタデータからリネーム
for %%a in ( *.mov ) do (
    call :subvideo "%%a"
)
echo mp4をメタデータからリネーム
for %%a in ( *.mp4 ) do (
    call :subvideo "%%a"
)


rem ==========終了==========
echo 処理完了
pause
exit


rem ==========画像を日付リネームサブルーチン==========
:subimage
rem ImageMagickのidentifyコマンドを使ってexif:DateTimeOriginalを出力し環境変数Exifに設定
rem magick identify -verbose %1 > Exif.txt で詳細出力可能
rem for /f "delims=" %%i in ('findstr "exif:DateTimeOriginal" "Exif.txt"') do (set EXIF=%%i)
for /f "delims=" %%a in ('magick identify -format "%%[exif:DateTimeOriginal]" %1') do (
    set "EXIF=%%a"
)
if not defined "%EXIF%" (
    call :noexif %1
)
rem %EXIF% "2017:12:18 12:53:24"(exif:DateTimeOriginal) "2017-12-18T12:53:30+09:00"(date:modify)->"171218_1253"
set EXIF=%EXIF:~2,2%%EXIF:~5,2%%EXIF:~8,2%_%EXIF:~11,2%%EXIF:~14,2%
echo src:%~1 dst:%EXIF%%~x1
if not exist %EXIF%%~x1 (
    ren %1 %EXIF%%~x1
) else if exist %EXIF%%~x1 (
    set cnt=0
    :loop
    set /a cnt=cnt+1
    if not exist %EXIF%_%cnt%%~x1 (
        ren %1 %EXIF%_%cnt%%~x1
    ) else if exist %EXIF%_%cnt%%~x1 (
        goto :loop
    )
)
exit /b

:noexif
for /f "delims=" %%a in ('magick identify -format "%%[date:modify]" %1') do (
    set EXIF=%%a
)
exit /b


rem ==========PNGをJPGに変換してPNGを削除サブルーチン==========
:subpngjpg
echo src:%~1 dst:%~n1.jpg
magick convert %1 -quality 79 "%~dpn1.jpg"
exit /b


rem ==========動画を日付リネームサブルーチン==========
:subvideo
rem ffprobeの-show_entriesスイッチを使ってformat_tags=com.apple.quicktime.creationdateを出力し環境変数Exifに設定
rem format_tags=creation_timeは世界標準時
for /f "delims=" %%a in ('ffprobe -v quiet -i %1 -show_entries format_tags^=com.apple.quicktime.creationdate -of default^=noprint_wrappers^=1:nokey^=1') do (
    set "EXIF=%%a"
)

rem %EXIF% "2018-01-26T19:07:41+0900"->"180126_1907"
set EXIF=%EXIF:~2,2%%EXIF:~5,2%%EXIF:~8,2%_%EXIF:~11,2%%EXIF:~14,2%
echo src:%~1 dst:%EXIF%%~x1
if not exist %EXIF%%~x1 (
    ren %1 %EXIF%%~x1
) else if exist %EXIF%%~x1 (
    set cnt=0
    :loop
    set /a cnt=cnt+1
    if not exist %EXIF%_%cnt%%~x1 (
        ren %1 %EXIF%_%cnt%%~x1
    ) else if exist %EXIF%_%cnt%%~x1 (
        goto :loop
    )
)
exit /b

没になったやつ

バッチ

@echo off
cd %1
for %%a in ( *.* ) do (
    call :sub "%%a"
)
exit /b

:sub
set EXIF=%~t1
set EXIF=%EXIF:~0,2%%EXIF:~3,2%%EXIF:~6,2%_%EXIF:~13,2%%EXIF:~16,2%
if not exist %EXIF%%~x1 (
    ren %1 %EXIF%%~x1
) else if exist %EXIF%%~x1 (
    set cnt=0
    :loop
    set /a cnt=cnt+1
    if not exist %EXIF%_%cnt%%~x1 (
        ren %1 %EXIF%_%cnt%%~x1
    ) else if exist %EXIF%_%cnt%%~x1 (
        goto :loop
    )
)
exit /b

解説

cd %1 D&Dしたフォルダをカレントディレクトリに
for %%a in ( *.* ) do call :sub "%%a" フォルダ内の全てのファイル*.*に対し再帰的に:subを呼び出す
set EXIF=%~t1 環境変数EXIFにファイルの日付時刻%~t1を指定
%EXIF:~0,2% 環境変数EXIFの前から0文字目~0から2文字2取得

私はここ↑で日付時刻の形式を変更しているので,これ↓にすると変な名前になっちゃう。あと英語版OSでもまた違ったりと…。
set EXIF=%EXIF:~0,2%%EXIF:~3,2%%EXIF:~6,2%_%EXIF:~13,2%%EXIF:~16,2% 例:17/08/30 (水) 17:35->170830_1735
多分初期設定ならこれ↓であってるはず。
set EXIF=%EXIF:~2,2%%EXIF:~5,2%%EXIF:~8,2%_%EXIF:~11,2%%EXIF:~14,2% 例:2017/08/30 17:35 -> 170830_1735

if not exist %EXIF%%~x1 (
    ren %1 %EXIF%%~x1
)

例:カレントディレクトリに170830_1735.jpgがなかったら170830_1735.jpgにリネーム

else if exist %EXIF%%~x1 (
    set cnt=0
    :loop
    set /a cnt=cnt+1
    if not exist %EXIF%_%cnt%%~x1 (
        ren %1 %EXIF%_%cnt%%~x1
    ) else if exist %EXIF%_%cnt%%~x1 (
        goto :loop
    )
)

例:カレントディレクトリに170830_1735.jpgがあったら170830_1735_1.jpgにリネーム,170830_1735_1.jpgがあったら170830_1735_2.jpg
callで呼ばれたif文内の%~x1とかって補完されなかった()けどcallで呼ばずに組み込めば動いた

応用

先程のバッチをちょっと弄るだけで,ファイル名からリネームしたりも出来るよ!

2017-08-30 17-35-29 -> 170830_1735

@echo off
cd %1
for %%a in ( *.* ) do call :sub "%%a"
exit /b

:sub
set EXIF=%~n1
set EXIF=%EXIF:~2,2%%EXIF:~5,2%%EXIF:~8,2%_%EXIF:~11,2%%EXIF:~14,2%
if not exist %EXIF%%~x1 (
    ren %1 %EXIF%%~x1
) else if exist %EXIF%%~x1 (
    set cnt=0
    :loop
    set /a cnt=cnt+1
    if not exist %EXIF%_%cnt%%~x1 (
        ren %1 %EXIF%_%cnt%%~x1
    ) else if exist %EXIF%_%cnt%%~x1 (
        goto :loop
    )
)
exit /b

[改訂新版]Windowsコマンドプロンプトポケットリファレンス

[改訂新版]Windowsコマンドプロンプトポケットリファレンス

  • 作者:山近 慶一
  • 発売日: 2016/03/04
  • メディア: 単行本(ソフトカバー)