PythonでEXIFに基づいてJPEGをリネームする

Share on:

画像ファイルが増えてきたので、ファイル名の命名ルールを決めて管理しようと思い、その命名ルールでファイルをリネームするプログラムを書いてみました。

命名ルール

ファイル名はyy-mm-dd-hh-mm-ss.jpgとしました。最初のmmは月で後のmmは分です。基本的に連射はしないので、撮影日時が秒単位で重なることはないと考えて、このファイル名にしました。

画像からexifの取得

PILのImageでOpenした画像から_getexif()でexifデータを辞書として取得できます。

1from PIL import Image
2image = Image.open(path)
3exif = image._getexif()

取得した辞書のキーはIDで数字になっているので、そのままでは何のデータなのか判別できません。そこで、PIL.ExifTags.TAGS.get()で下記のように辞書内包表記でIDを名前に変更します。

1exif = { TAGS.get(key, key):exif[key] for key in exif.keys() }

これでexifの辞書からタグ名で取得できるようになります。撮影日時の取得は下記のように取得できます。

1date_time_original = exif.get('DateTimeOriginal')

この処理で取得したデータはyyyy:mm:dd hh:mm:ssという文字列として得られるので、:を-に置き換えてスペースを-に置き換え、最初の2文字を除くと、今回の命名ルールの文字列になるので下記のように文字列処理をしています。

1date_time_original = date_time_original.replace(':', '-').replace(' ', '-')
2date_time_original = date_time_original[2:]

EXIFから取得できなかった時の処理

EXIFがなかった場合、あるいはEXIFにDateTimeOriginalが無かった場合はファイルの作成日時からファイル名を決定する処理にしました。今回の環境はwindowsなので、ファイルの作成日時はpathlib.Path().stat().st_ctimeで取得でき、その取得したデータから下記のようにファイル名を決定しました。

1d = datetime.datetime.fromtimestamp( path.stat().st_ctime )
2d = str(d).replace(':', '-').replace(' ', '-').split('.')[0][2:]
3renamed = folder + '/' + d + path.suffix

これらの処理で画像ファイルをすべてリネームすることにしました。コード全体は下記の通りです。

ソースコード

 1from pathlib import Path
 2from PIL import Image
 3from PIL.ExifTags import TAGS
 4import shutil
 5import datetime
 6
 7def path_rename_datetime_from_exif(path, folder):
 8    image = Image.open(path)
 9    
10    try:
11        exif = image._getexif()
12    except AttributeError:
13        return get_creat_time(path, folder)
14    
15    if exif is None:
16        return get_creat_time(path, folder)
17
18    # replace TAG ID to name
19    exif = { TAGS.get(key, key):exif[key] for key in exif.keys() }
20
21    date_time_original = exif.get('DateTimeOriginal')
22
23    if date_time_original is None:
24        return get_creat_time(path, folder)
25
26    date_time_original = date_time_original.replace(':', '-').replace(' ', '-')
27    date_time_original = date_time_original[2:]
28
29    renamed = folder + '/' + date_time_original + path.suffix
30    renamed = Path(renamed)
31
32    return renamed
33
34def get_creat_time(path, folder):
35    d = datetime.datetime.fromtimestamp( path.stat().st_ctime )
36    d = str(d).replace(':', '-').replace(' ', '-').split('.')[0][2:]
37    renamed = folder + '/' + d + path.suffix
38    return Path(renamed)
39
40def main():
41    paths = list( Path('D:/Picture').glob('*.jpg') )
42    renamed = [ path_rename_datetime_from_exif(path, 'renamed_folder') for path in paths ]
43
44    for path, rename in zip(paths, renamed):
45        shutil.copy(path, rename)
46
47if __name__ == "__main__":
48    main()

関連記事