之前的笔记 Python 照片批量重命名 记录了使用 exifread 包读取照片 EXIF 信息以及批量重命名文件的脚本。实际使用下来发现很多照片的拍摄日期信息无法获取。

看到很多人介绍使用 PIL,但看到项目主页最版新只支持到 Python 2.6,后来才发现已经有人创建了新分支 Pillow,实测支持 Python 3.7.0。这个库功能非常丰富,可以对照片做非常专业的处理,读取 EXIF 信息确实有些杀鸡用牛刀,但它实在简单好用。

安装 Pillow

$ pipenv install pillow

批处理脚本

import os
from PIL import Image
import hachoir.parser
import hachoir.metadata


def pic_rename(target_dir, filename, file_ext):
    p = Image.open(target_dir + filename)
    if p._getexif() and 36867 in p._getexif():
        DateTimeOriginal = p._getexif()[36867]
        the_date = DateTimeOriginal.split()[0].replace(':', '-')
        formated_name = the_date + '_' + \
            DateTimeOriginal.split()[1].replace(':', '') + file_ext

        os.rename(target_dir + filename, target_dir + formated_name)
        print('新文件名:' + formated_name)

    else:
        print('跳过:未找到时间信息!')


def vedio_rename(target_dir, filename, file_ext):
    # 解析文件
    the_file = hachoir.parser.createParser(target_dir + filename)
    if the_file:
        try:
            info = hachoir.metadata.extractMetadata(the_file)
        except Exception as err:
            print("元数据提取错误: %s" % err)
            info = None
            
        if info:
            for line in info.exportPlaintext():
                if 'Creation date' in line:
                    original_date = line.replace(
                        '- Creation date:', '').strip().split()
                    formated_name = original_date[0] + '_' + \
                        original_date[1].replace(':', '') + file_ext
                    os.rename(target_dir + filename,
                              target_dir + formated_name)
                    print('新文件名:' + formated_name)
                    
        else:
            print('无法提取元数据!')
    else:
        print('无法解析文件!')


def bulk_media_rename(target_dir):
    for file in os.listdir(target_dir):
        print('源文件:' + file)
        file_ext = file[file.find('.'):].lower()
        if file_ext in ['.jpg']:
            pic_rename(target_dir, file, file_ext)
        elif file_ext in ['.mp4', '.mov']:
            vedio_rename(target_dir, file, file_ext)
        else:
            print('跳过:不支持的文件格式!')


target_dir = '/Volumes/Memory/未整理/jeju/'
bulk_media_rename(target_dir)

执行结果:

源文件:IMG_4107.JPG
修改为:2017-04-29_145724.jpg
源文件:test
跳过:不支持的文件格式!
源文件:IMG_0694.mp4
跳过:不支持的文件格式!
源文件:IMG_0564.MOV
跳过:不支持的文件格式!
源文件:IMG_0678.JPG
跳过:未找到时间信息!

参考