Python实战:如何用脚本批量重命名文件?从入门到精通
目录导读
为什么需要批量重命名?
在日常工作中,我们经常遇到以下场景:

- 摄影爱好者整理照片,需要按拍摄时间统一命名(如
2025_04_08_001.jpg) - 数据分析师处理大量CSV文件,需要去掉后缀中的乱码字符
- 程序员下载的素材文件名称混杂着特殊符号,影响脚本读取
手动逐个修改几百个文件,不仅耗时且极易出错,Python的os和shutil模块提供了高效的系统接口,而pathlib模块则用面向对象的方式简化路径操作,掌握批量重命名,能显著提升文件管理效率。
核心Python库介绍
| 库名称 | 核心功能 | 适用场景 |
|---|---|---|
os |
系统级文件操作(rename, listdir) | 快速基础重命名 |
pathlib |
面向对象的路径处理 | 路径拼接、通配符匹配 |
re |
正则表达式匹配替换 | 复杂模式查找与替换 |
shutil |
复制、移动文件 | 备份后重命名 |
datetime |
日期时间格式化 | 按时间戳命名文件 |
推荐使用pathlib,因为它跨平台友好且代码更简洁。
from pathlib import Path
# 遍历目录下所有.txt文件
for file in Path('.').glob('*.txt'):
print(file.name)
基础案例:统一添加前缀/后缀
需求:为当前目录下所有pdf文件添加“报告_”前缀。
代码实现:
import os
from pathlib import Path
def add_prefix(prefix='报告_', ext='.pdf'):
folder = Path('.')
for file in folder.glob(f'*{ext}'):
if file.is_file():
new_name = prefix + file.name
file.rename(file.parent / new_name)
print(f'已重命名: {file.name} -> {new_name}')
if __name__ == '__main__':
add_prefix()
运行结果:
readme.pdf→报告_readme.pdf数据.pdf→报告_数据.pdf
注意:代码会直接修改文件,建议先在小文件夹内测试,若想添加后缀(如
_v2),只需将new_name改为file.stem + suffix + ext(file.stem是文件名不含扩展名的部分)。
进阶案例:按创建日期重命名
需求:将图片文件的名称统一改为“拍摄日期_序号.jpg”。
代码实现:
from pathlib import Path
import datetime
import os
def rename_by_date(ext='.jpg'):
folder = Path('.')
files = sorted(folder.glob(f'*{ext}'),
key=lambda f: os.path.getmtime(f))
for idx, file in enumerate(files, start=1):
timestamp = os.path.getmtime(file) # 获取修改时间(Unix时间戳)
date_str = datetime.datetime.fromtimestamp(timestamp).strftime('%Y%m%d')
new_name = f'{date_str}_{idx:03d}{ext}'
file.rename(folder / new_name)
print(f'{file.name} -> {new_name}')
rename_by_date()
输出示例:
P1234.jpg(2025-04-08 10:30创建)→20250408_001.jpgIMG_5678.jpg(2025-04-08 11:00创建)→20250408_002.jpg
注意:这里使用getmtime(最后修改时间),如果你想用“创建时间”,在Windows上可用os.path.getctime;在macOS/Linux上注意区分。
正则表达式高级替换
需求:移除文件名中的括号、空格和乱码字符,并替换为下划线。
代码实现:
import re
from pathlib import Path
def clean_filename(file):
"""清理文件名中的特殊字符"""
name = file.stem
ext = file.suffix
# 替换非字母数字字符为下划线
clean = re.sub(r'[^\w\u4e00-\u9fff]', '_', name) # 保留中文
# 合并连续下划线
clean = re.sub(r'_+', '_', clean)
# 去掉开头和结尾的下划线
clean = clean.strip('_')
return clean + ext
def batch_clean():
folder = Path('.')
for file in folder.iterdir():
if file.is_file():
new_name = clean_filename(file)
if new_name != file.name:
file.rename(folder / new_name)
print(f'清理: {file.name} -> {new_name}')
batch_clean()
正则说明:
[^\w\u4e00-\u9fff]:匹配非单词字符(字母、数字、下划线)和非中文(Unicode范围)的字符- 匹配一个或多个连续下划线
常见替换场景:
- 删除所有空格:
re.sub(r'\s+', '', name) - 将日期从“2025-04-08”改为“20250408”:
re.sub(r'(\d{4})-(\d{2})-(\d{2})', r'\1\2\3', name)
安全与备份策略
最佳实践:
-
先预览再执行:在正式修改前,先
print出新旧名称对,而不是直接执行rename。print(f'将要重命名: {old} -> {new}') # 确认无误后再执行 # Path(old).rename(new) -
操作前备份:用
shutil.copy2复制文件到备份目录。import shutil backup_dir = Path('./backup') backup_dir.mkdir(exist_ok=True) shutil.copy2(file, backup_dir / file.name) -
避免命名冲突:如果新文件名已存在,
rename会直接覆盖,建议检查:if new_file.exists(): print(f'跳过:{new_file} 已存在') continue -
处理子目录:使用
rglob('*')递归遍历子文件夹,注意路径拼接。
常见问题问答(FAQ)
Q1:批量重命名时,如何保留原始文件的创建时间和修改时间?
A:os.rename会保留时间戳,但如果你使用shutil.move,可以确保元数据不变,推荐:
shutil.move(old_path, new_path) # 保留权限和时间
Q2:文件数量非常多(超过10万),脚本会不会卡死?
A:建议使用生成器而非一次性加载全部文件列表。Path.glob本身就是生成器,不会一次性占用大量内存,如果确实需要分批处理,可以使用itertools.islice限制每次处理数量。
Q3:我想让文件名按规则递增序号,但已有文件名存在跳跃(如1,3,5),怎么重新从1开始?
A:使用enumerate(files, start=1)重新编号即可,如第4节案例代码所示,如果希望按字母顺序排序,加上sorted()。
Q4:正则替换后,文件名变成空字符串了怎么办? A:加个默认名称保护:
if not clean:
clean = 'unnamed'
file.rename(folder / (clean + ext))
Q5:我的文件名包含乱码或无法解码的字符,Python报错怎么办?
A:使用file.name.encode('utf-8', errors='ignore').decode('utf-8')忽略错误字符,或者在重命名时用Path(new_name)强制使用Unicode编码。
批量重命名文件看似简单,实则在细节处考验开发者的工程思维,从基础的os.rename到面向对象的pathlib,再到正则表达式的灵活运用,Python提供了从简单到复杂的全套解决方案,建议读者先从“预览模式”开始尝试,再逐步添加备份、日志等功能,当你需要处理几百个文件时,这些脚本将成为你节省时间的利器,如果你有其他独特的需求(如按文件内容重命名、或从Excel列表匹配重命名),欢迎在评论区留言探讨。