#### カレントディレクトリで,引数に指定したファイル名を撮影日時を付けて一括変換するbashスクリプト Last update 2020-05-28_1408

:CATEGORIES: スクリプト,bash



[5294] % file 2016-11-05_130911_珠洲市木ノ浦海岸から釣ってきた小鯛から出てきたタイノエ.jpg
2016-11-05_130911_珠洲市木ノ浦海岸から釣ってきた小鯛から出てきたタイノエ.jpg: JPEG image data, Exif standard: [TIFF image data, big-endian, direntries=8, manufacturer=HTC, model=HTL21, xresolution=294, yresolution=302, resolutionunit=2, GPS-Data], baseline, precision 8, 3264x1840, components 3

 コマンドの実行結果に「JPEG image data, Exif standard:」という情報があります。これがスクリーンショットのjpgだと違っていたと思います。


[5295] % file 2020-05-28-090058_深澤諭史さんがリツイート蛇毒@bigbrother939·8時間他人のツイートを見て自分のこと言われているんじゃないか、馬鹿にされているんじゃないかと思う.jpg
2020-05-28-090058_深澤諭史さんがリツイート蛇毒@bigbrother939·8時間他人のツイートを見て自分のこと言われているんじゃないか、馬鹿にされているんじゃないかと思う.jpg: JPEG image data, JFIF standard 1.01, aspect ratio, density 1x1, segment length 16, baseline, precision 8, 1160x935, components 3

 写真ファイルの「JPEG image data, Exif」の部分が,「JPEG image data, JFIF」になっていました。JFIFというのは今初めて見たように思うのですが,これをキーワードに調べればわかることがあると思います。


JFIFとは、JPEG形式の画像データをファイルに記録するための形式を定めた標準規格の一つ。ファイル名の標準の拡張子は「.jpg」あるいは「.jpeg」。

[source:]JFIFJPEG File Interchange Format)とは - IT用語辞典 e-Words http://e-words.jp/w/JFIF.html

 ExifJFIFの拡張領域になるようなことが書いてありました。次にjheadというコマンドを使って情報を確認しました。


[5296] % jhead 2020-05-28-090058_深澤諭史さんがリツイート蛇毒@bigbrother939·8時間他人のツイートを見て自分のこと言われているんじゃないか、馬鹿にされているんじゃないかと思う.jpg
File name : 2020-05-28-090058_深澤諭史さんがリツイート蛇毒@bigbrother939·8時間他人のツイートを見て自分のこと言われているんじゃないか、馬鹿にされているんじゃないかと思う.jpg
File size : 196630 bytes
File date : 2020:05:28 09:01:01
Resolution : 1160 x 935
JPEG Quality : 75

 試しにファイルをコピーしてみたのですが,コピーしたファイルも「File date : 2020:05:28 09:01:01」の部分が同じでした。この値を使えば,スクリーンショットの時刻をファイル名に使うことが出来ます。次に写真のjpgファイルの情報です。


[5297] % jhead 2016-11-05_130903_珠洲市木ノ浦海岸から釣ってきた小鯛から出てきたタイノエ.jpg
File name : 2016-11-05_130903_珠洲市木ノ浦海岸から釣ってきた小鯛から出てきたタイノエ.jpg
File size : 2755223 bytes
File date : 2017:02:18 22:06:43
Camera make : HTC
Camera model : HTL21
Date/Time : 2016:11:05 13:09:03
Resolution : 3264 x 1840
Flash used : No
Focal length : 3.6mm
Exposure time: 0.0083 s (1/120)
Aperture : f/2.0
ISO equiv. : 221
Metering Mode: center weight
GPS Latitude : N 37d 18m 34.9063s
GPS Longitude: E 137d 9m 13.2714s
GPS Altitude : 0.00m
JPEG Quality : 95

 スクリーンショットでは4つだった情報がざっと数えて17に増えています。撮影したスマホの機種がHTC21ということもわかります。Androidスマホです。iphoneに変更したのが2017年5月で,七尾市の青柏祭に行った時のことでした。ついでに機種変更をしてきました。

 次がスクリプトのファイルになります。

#!/bin/bash
IFS=

#rename s/\.JPG/\.jpg/ ./*.JPG

echo "#{$#}件が処理の対象になります。"
echo "追加する文字列を入力:"
read name
	name=${name//\!/}
	name=${name//\//}
	name=${name//\ / }
	name=${name//#/#}
	name=${name//%/}
	name=${name//$/}
	name=${name//&/}
	name=${name//\'/}
	name=${name//\"/}
	name=${name//\*/}
	name=${name//\+/}
	name=${name//\~/}
	name=${name//\^/}
	name=${name//\|/}
	name=${name//\`/}
	name=${name//@/}
	name=${name//\\/}
	name=${name//\(/}
	name=${name//\)/}
	name=${name//\{/}
	name=${name//\}/}
	name=${name//\[/}
	name=${name//\]/}

function frename() {
	#date=`jhead $1 |sed -n -e 's/^Date\/Time    : \(....\):\(..\):\(..\) \(..\):\(..\):\(..\)/\1-\2-\3_\4\5\6/p'`
	base=${1%%.jpg}
	ext=${1##*.}
	date=`jhead $1 |sed -n -e 's/^Date\/Time    : \(....\):\(..\):\(..\) \(..\):\(..\):\(..\)/\1-\2-\3_\4\5\6/p'`
	newname=${date}_${name}.$ext
	mv $1 ${newname}
	echo "new filename ---> ${newname}"

}
	
while [ "$#" -gt 0 ]    #引数の数だけループさせる
do
    #echo ${1}    #第一引数を表示
    fname=$1
    chk=`echo $1 |egrep ' '| wc -c` #ファイル名に半角スペースが含まれていないかチェック。文字列に含まれる文字を調べる。
    if [ $chk -eq 0 ] ; then
        :
    else
        rname=${fname//\ /_}
        mv $fname $rname
        fname=$rname
    fi
    
    frename ${fname}
    shift
done

 半角の#より後ろの部分はコメントアウトになり,処理は実行されません。ただプログラムの本体では半角の#を使うこともあり,文字列の一部である以外は組み合わせなどで特別な働きをします。

 「rename s/\.JPG/\.jpg/ ./*.JPG」という部分も最近加えたものですが,意図したような動作をしませんでした。修正の必要があったのですが,続きの作業をやっておらず,今回は念の為コメントアウトにしておきました。

 事前に「rename s/\.JPG/\.jpg/ ./*.JPG」を実行すればよい話なのですが,その手間も省いておきたいと考えたのです。iCloudでダウンロードしたファイルもそうなのですが,拡張子がJPGという大文字になっています。

 「date=`jhead $1 |sed -n -e 's/^Date\/Time : \(....\):\(..\):\(..\) \(..\):\(..\):\(..\)/\1-\2-\3_\4\5\6/p'`」という部分で,書式変換した撮影時刻を変数に代入しています。

 「args-jpg-filename-new-date-format-word.sh ./*.jpg」というのがコマンドの実行になります。jpgを拡張子に持つカレントディレクトリのファイルを全て引数に渡しています。これはシェルのワイルドカードです。プログラム内の正規表現とは別物です。

 「2016-11-04_183548_.jpg」というファイル名は,このスクリプトで作ったものになりますが,「追加する文字列を入力:」は未入力のままエンターキーを押しています。ここで文字列を指定すると対象のファイル全てに共通したワードになります。

 最近は面倒になってきてファイル名のワードを入れないようになっています。余り入れない方が,入れたものの存在が目立つということもありますが,なるべく時間を掛けたくないというのが大きいです。

 ディレクトリというかフォルダのコピーをとってから処理をすれば安全対策は万全かと思います。便利だけどリスクもともなうのがスクリプトの処理になります。動画ファイルのファイル名変更は確認をしてから実行するように組んでいますが,jpgは数も多いので入れていません。

 なお,スクリーンショットの場合は,スクリプトでファイルの保存時に自動生成したファイル名を使っています。まとめて処理するという発想がスクリーンショットの場合はなかったのですが,簡単にできそうなことが今日になってわかりました。

 写真ファイルのファイル名変更に使っているのが「Date/Time」という項目の値,これをスクリーンショットの場合は「File date」の値にすればよさそうです。余り必要性は感じないですが,ファイル名の書式については前から改良を考えています。