用 Python 批量改文件名
文件批量重命名是常见需求,本文介绍几种实用的 Python 方案。
1. 基本重命名
使用 pathlib
from pathlib import Path
folder = Path("images")
for p in folder.glob("*.png"):
new_name = p.stem.replace(" ", "_") + ".png"
p.rename(p.parent / new_name)
使用 os.rename
import os
folder = "images"
for filename in os.listdir(folder):
if filename.endswith(".png"):
old_path = os.path.join(folder, filename)
new_name = filename.replace(" ", "_")
new_path = os.path.join(folder, new_name)
os.rename(old_path, new_path)
2. 常用重命名模式
添加前缀
from pathlib import Path
folder = Path("documents")
for p in folder.iterdir():
if p.is_file():
p.rename(p.parent / f"backup_{p.name}")
添加序号
from pathlib import Path
folder = Path("photos")
for i, p in enumerate(sorted(folder.glob("*.jpg")), start=1):
new_name = f"img_{i:03d}{p.suffix}"
p.rename(p.parent / new_name)
# img_001.jpg, img_002.jpg, ...
统一扩展名
from pathlib import Path
folder = Path("documents")
for p in folder.glob("*.JPEG"):
p.rename(p.with_suffix(".jpg"))
3. 使用正则表达式
import re
from pathlib import Path
folder = Path("files")
for p in folder.glob("*"):
if p.is_file():
# 移除日期前缀 2024-01-01_
new_name = re.sub(r'^\d{4}-\d{2}-\d{2}_', '', p.name)
if new_name != p.name:
p.rename(p.parent / new_name)
4. 批量重命名函数
import os
from pathlib import Path
import re
def batch_rename(
folder: str,
pattern: str = "*",
rename_func=None,
dry_run: bool = True
):
"""批量重命名文件
Args:
folder: 文件夹路径
pattern: 文件匹配模式
rename_func: 重命名函数,接受文件名返回新文件名
dry_run: True 则只打印不实际执行
"""
folder = Path(folder)
results = []
for p in folder.glob(pattern):
if not p.is_file():
continue
new_name = rename_func(p.name)
if new_name and new_name != p.name:
results.append((p.name, new_name))
if not dry_run:
p.rename(p.parent / new_name)
print(f"重命名: {p.name} -> {new_name}")
return results
# 使用示例:去除空格
batch_rename("images", "*.png", lambda name: name.replace(" ", "_"))
# 使用示例:转小写
batch_rename("images", "*.png", lambda name: name.lower())
# 使用示例:添加日期前缀
from datetime import datetime
batch_rename("files", "*",
lambda name: f"{datetime.now().strftime('%Y%m%d')}_{name}")
5. 带冲突处理
from pathlib import Path
from collections import Counter
def safe_rename(folder, pattern, rename_func):
"""安全重命名,处理文件名冲突"""
folder = Path(folder)
# 第一步:生成所有新文件名
changes = []
for p in folder.glob(pattern):
if p.is_file():
new_name = rename_func(p.name)
changes.append((p, new_name))
# 检测冲突
new_names = [c[1] for c in changes]
duplicates = [k for k, v in Counter(new_names).items() if v > 1]
if duplicates:
print(f"警告:以下新文件名会冲突: {duplicates}")
return
# 执行重命名
for old_path, new_name in changes:
if new_name != old_path.name:
old_path.rename(old_path.parent / new_name)
print(f"{old_path.name} -> {new_name}")
# 使用
safe_rename("images", "*.png", lambda n: n.replace(" ", "_"))
6. 实际应用示例
整理下载文件
from pathlib import Path
import shutil
downloads = Path("/Users/hao/Downloads")
# 按文件类型分类
for p in downloads.iterdir():
if not p.is_file():
continue
ext = p.suffix.lower().replace(".", "")
dest = downloads / ext
if not dest.exists():
dest.mkdir()
shutil.move(str(p), str(dest / p.name))
print(f"移动 {p.name} -> {dest.name}/")
处理照片
from pathlib import Path
from datetime import datetime
photos = Path("photos")
# 从 EXIF 获取拍摄日期(需要 Pillow)
from PIL import Image
from PIL.ExifTags import TAGS
for p in photos.glob("*.jpg"):
try:
img = Image.open(p)
exif = {TAGS[k]: v for k, v in img._getexif().items() if k in TAGS}
date = exif.get("DateTimeOriginal")
if date:
dt = datetime.strptime(date, "%Y:%m:%d %H:%M:%S")
new_name = dt.strftime("%Y%m%d_%H%M%S") + ".jpg"
p.rename(p.parent / new_name)
print(f"{p.name} -> {new_name}")
except:
continue
7. 完整脚本示例
#!/usr/bin/env python3
"""批量文件重命名工具"""
import argparse
from pathlib import Path
def main():
parser = argparse.ArgumentParser(description="批量重命名文件")
parser.add_argument("folder", help="目标文件夹")
parser.add_argument("--pattern", default="*", help="文件匹配模式")
parser.add_argument("--replace", help="要替换的字符串")
parser.add_argument("--with", dest="replacement", help="替换为的字符串")
parser.add_argument("--prefix", help="添加前缀")
parser.add_argument("--suffix", help="添加后缀")
parser.add_argument("--execute", action="store_true", help="实际执行(默认只预览)")
args = parser.parse_args()
folder = Path(args.folder)
for p in folder.glob(args.pattern):
if not p.is_file():
continue
name = p.name
stem = p.stem
suffix = p.suffix
# 应用转换
if args.replace:
new_stem = stem.replace(args.replace, args.replacement or "")
else:
new_stem = stem
if args.prefix:
new_stem = args.prefix + new_stem
if args.suffix:
new_stem = new_stem + args.suffix
new_name = new_stem + suffix
if new_name != name:
print(f"{name} -> {new_name}")
if args.execute:
p.rename(p.parent / new_name)
if __name__ == "__main__":
main()
使用:
# 预览
python rename.py images --pattern "*.png" --replace " " --with "_"
# 执行
python rename.py images --pattern "*.png" --replace " " --with "_" --execute
# 添加前缀
python rename.py photos --pattern "*.jpg" --prefix "vacation_"
快速对照表
| 方法 | 用途 |
|---|---|
Path.rename() |
基本重命名 |
shutil.move() |
移动文件 |
Path.glob() |
模式匹配 |
re.sub() |
正则替换 |
Python 批量重命名灵活可控,是处理文件的好帮手。