批量重命名需先排序再重命名:用 sorted() 配合数字提取避免字符串排序错误,统一转绝对路径,预览确认后执行;保留原扩展名、补零对齐、检查目标存在、优先用创建时间或 EXIF 时间防冲突,注意中文路径和文件占用问题。

用 os.rename() 批量重命名前必须先确认路径和顺序
直接循环调用 os.rename() 很容易出错,不是文件找不到,就是重命名时覆盖或乱序。根本原因是:Python 读取目录下文件的顺序不保证是自然排序(比如 img1.jpg、img10.jpg、img2.jpg 会被按字符串排成 1, 10, 2)。你得自己排序,而且得用绝对路径或统一工作目录,否则相对路径一错全错。
- 先用
os.listdir()或glob.glob()获取文件列表,再用sorted()+re.findall(r'\d+', name)做数字提取排序(避免字符串排序翻车) - 所有路径建议转成绝对路径:
os.path.abspath(),尤其跨目录操作时 - 重命名前加个预览步骤:先
print(f"{old} → {new}"),确认无误再执行os.rename() - 别在原图目录里边读边写——如果新名和旧名前缀一样,可能刚重命名一个,下一个就找不到了(比如把
a1.jpg改成001.jpg,接着又去处理a2.jpg,但脚本误把001.jpg当成待处理文件)
按递增数字重命名要防「覆盖」和「位数对齐」
很多人写 i = 1; for f in files: os.rename(f, f"img{i}.jpg"); i += 1,结果发现有些图没了——其实是后缀不统一(.JPG、.png、.jpeg),强行改成 .jpg 导致同名覆盖;还有人没补零,img1.jpg 到 img100.jpg 排序混乱。
- 保留原始扩展名:
os.path.splitext(old_name)[1].lower(),别硬写死.jpg - 用
f"{i:03d}"补零(如 1→001),避免排序错乱;位数根据总数定,137 张图就用:03d,1200 张用:04d - 检查目标文件是否已存在:
if not os.path.exists(new_path): os.rename(...),否则跳过或报错提示 - 别用
range(len(files)),直接用enumerate(files, start=1)更安全
按修改时间重命名需注意时区和精度丢失
os.path.getmtime() 返回的是时间戳(秒级浮点数),同一秒内改的多个文件会拿到相同时间戳,直接用它生成名字(比如 f"{int(mtime)}_{i}.jpg")会导致冲突;Windows 和 Linux 下的「修改时间」行为也不一致——Windows 资源管理器复制文件时默认更新 mtime,而 Linux cp 不更新(除非加 -p)。
- 优先用
os.path.getctime()(创建时间)更稳定,但 macOS 上 ctime 是状态变更时间,不等于创建时间 - 组合使用时间戳 + 序号:
f"{int(mtime)}_{i:02d}{ext}",确保同秒内不冲突 - 时间格式化推荐
datetime.fromtimestamp(mtime).strftime("%Y%m%d_%H%M%S"),但要注意:秒级精度不够时,后面还得补序号 - 如果文件是从手机导出的,EXIF 里的拍摄时间更准,此时该用
PIL.Image或exifread读取,而不是依赖文件系统时间
Windows 下中文路径和权限问题最常卡住脚本
报错 FileNotFoundError: [WinError 2] 系统找不到指定的文件 或 PermissionError: [WinError 5] 拒绝访问,八成是路径含中文没处理好,或者文件被资源管理器/看图软件锁住了。
立即学习“Python免费学习笔记(深入)”;
- Windows 默认 cmd 不支持 UTF-8,脚本开头加
# -*- coding: utf-8 -*-不够,还要在代码里设sys.stdout.reconfigure(encoding='utf-8')(Python 3.7+) - 用
pathlib.Path替代os.path,它对中文路径兼容更好:p = Path("照片/2023年") / "IMG_001.JPG" - 重命名前加
try/except捕获PermissionError,并提示用户关闭预览窗体或杀掉占用进程(如explorer.exe有时会锁图) - 别用管理员权限强行跑——大部分时候不是权限不够,而是路径或编码错了
事情说清了就结束










