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

2020/07/25 categories:Python| tags:Python|PIL|exif|pathlib|

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

命名ルール

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

画像からexifの取得

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

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

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

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

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

date_time_original = exif.get('DateTimeOriginal')

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

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

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

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

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

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

ソースコード

from pathlib import Path
from PIL import Image
from PIL.ExifTags import TAGS
import shutil
import datetime

def path_rename_datetime_from_exif(path, folder):
    image = Image.open(path)
    
    try:
        exif = image._getexif()
    except AttributeError:
        return get_creat_time(path, folder)
    
    if exif is None:
        return get_creat_time(path, folder)

    # replace TAG ID to name
    exif = { TAGS.get(key, key):exif[key] for key in exif.keys() }

    date_time_original = exif.get('DateTimeOriginal')

    if date_time_original is None:
        return get_creat_time(path, folder)

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

    renamed = folder + '/' + date_time_original + path.suffix
    renamed = Path(renamed)

    return renamed

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

def main():
    paths = list( Path('D:/Picture').glob('*.jpg') )
    renamed = [ path_rename_datetime_from_exif(path, 'renamed_folder') for path in paths ]

    for path, rename in zip(paths, renamed):
        shutil.copy(path, rename)

if __name__ == "__main__":
    main()

Share post

Related Posts

コメント