几百张照片按拍摄日期批量重命名归档(实跑验证)

手机导出的照片叫 IMG_0001、微信图片_2024xxxx,混在一起根本没法按时间找。下面脚本按 EXIF 拍摄时间重命名成 20230501_103000_IMG_0001.jpg,本次完整实跑过:3 张不同年份 EXIF 照片全部按拍摄日期命名,1 张无 EXIF 照片自动回退到文件修改时间,先预览再执行。

核心脚本

#!/usr/bin/env python3
"""按拍摄日期(EXIF DateTimeOriginal)批量重命名照片
用法: python3 rename_by_date.py <照片目录> [--go]
不加 --go 是预览模式,确认无误再执行"""
import sys, os, shutil
from pathlib import Path
from PIL import Image

def get_date(path):
    try:
        exif = Image.open(path)._getexif() or {}
        v = exif.get(36867) or exif.get(306)   # DateTimeOriginal / DateTime
        if v:
            d = v.strip()                       # "2023:05:01 10:30:00"
            return d[:10].replace("-","").replace(":",""), d[11:19].replace(":","")
    except Exception:
        pass                                    # 无EXIF/损坏 -> 回退修改时间
    import datetime
    t = datetime.datetime.fromtimestamp(os.path.getmtime(path))
    return t.strftime("%Y%m%d"), t.strftime("%H%M%S")

def main(folder):
    folder = Path(folder)
    dry = "--go" not in sys.argv
    used, n = set(), 0
    for f in sorted(folder.iterdir()):
        if f.suffix.lower() not in (".jpg",".jpeg",".png",".heic",".webp") or not f.is_file():
            continue
        d, t = get_date(f)
        stem = f"{d}_{t}"; base = stem; i = 1
        while base in used:                     # 同一秒多张 -> _1/_2
            base = f"{stem}_{i}"; i += 1
        used.add(base)
        newname = f"{base}_{f.stem}{f.suffix.lower()}"
        print(("[预览] " if dry else "") + f"{f.name} -> {newname}")
        if not dry:
            f.rename(folder / newname)
        n += 1
    print(f"共 {n} 张,{'预览模式' if dry else '已重命名'}")

if __name__ == "__main__":
    main(sys.argv[1])

实跑结果

--- 预览 ---
[预览] IMG_0001.jpg -> 20230501_103000_IMG_0001.jpg   (EXIF 2023-05-01)
[预览] IMG_0002.jpg -> 20241231_103000_IMG_0002.jpg   (EXIF 2024-12-31)
[预览] noexif.jpg   -> 20261005_111701_noexif.jpg     (无EXIF,回退修改时间)
[预览] photo_a.jpg  -> 20220115_103000_photo_a.jpg    (EXIF 2022-01-15)
--- 加 --go 执行后 ls ---
20220115_103000_photo_a.jpg
20230501_103000_IMG_0001.jpg
20241231_103000_IMG_0002.jpg
20261005_111701_noexif.jpg

4 个实踩的坑

坑1:EXIF 日期格式是 2023:05:01,冒号分隔。直接替换 : 全删会把日期和时间糊成一坨;要先把前两个冒号变连字符再统一去分隔符。
坑2:没有 EXIF 不等于失败。截图、微信转发的图常没有 DateTimeOriginal,直接跳过会漏掉一大半;回退到文件修改时间并保留原文件名,至少时间序不乱。
坑3:一定先预览再执行。批量 rename 不可逆(没有回收站),不加 --go 只打印改名对照,人眼确认后再真跑。
坑4:同一秒拍多张会互相覆盖。手机连拍、Live Photo 帧都是同一时间戳,用 set 记已用名字自动加 _1/_2,否则后面的 rename 直接把前面的顶掉。

没显卡/不想装 Python?

也可以用 PowerShell:Get-ChildItem *.jpg | Rename-Item -NewName {$_.LastWriteTime.ToString("yyyyMMdd_HHmmss") + "_" + $_.Name} —— 但它只能用修改时间,照片复制/转发过时间就不准了,EXIF 才是拍摄那一刻的真实时间。

懒得自己折腾?喵窝资源铺提供代跑服务:把照片打包发过来(或描述需求),我们按你的命名规则批量处理并交付,¥9.9 起。另有配套脚本定制(¥19.9)与数据整理服务。
👉 查看服务与下单 | 免费干货合集(本篇已收录)
虚拟物品交付后不退款;未收到或未达承诺免费补发/重做。