本文目录导读:

我来为您提供几个Python批量重命名照片的案例,从简单到复杂:
案例1:基础批量重命名(按数字序号)
import os
import glob
def batch_rename_basic(folder_path, prefix="photo", start_num=1):
"""
基础批量重命名:按数字序号重命名
"""
# 获取所有图片文件
image_extensions = ['*.jpg', '*.jpeg', '*.png', '*.gif', '*.bmp']
image_files = []
for ext in image_extensions:
image_files.extend(glob.glob(os.path.join(folder_path, ext)))
# 按文件名排序
image_files.sort()
# 批量重命名
for i, old_path in enumerate(image_files, start_num):
# 获取文件扩展名
ext = os.path.splitext(old_path)[1]
# 新文件名(使用3位数字,不足补零)
new_name = f"{prefix}_{i:03d}{ext}"
new_path = os.path.join(folder_path, new_name)
# 执行重命名
os.rename(old_path, new_path)
print(f"已重命名: {os.path.basename(old_path)} -> {new_name}")
# 使用示例
batch_rename_basic(r"D:\照片文件夹", "vacation", 1)
案例2:按拍摄日期重命名
import os
from PIL import Image
from datetime import datetime
def batch_rename_by_date(folder_path):
"""
按照片拍摄日期重命名
"""
image_extensions = ['jpg', 'jpeg', 'png', 'gif']
for filename in os.listdir(folder_path):
if any(filename.lower().endswith(ext) for ext in image_extensions):
old_path = os.path.join(folder_path, filename)
try:
# 获取照片EXIF信息
image = Image.open(old_path)
exif = image.getexif()
# 获取拍摄时间
if 36867 in exif: # DateTimeOriginal
date_str = exif[36867]
elif 306 in exif: # DateTime
date_str = exif[306]
else:
# 如果没有EXIF信息,使用文件修改时间
date_str = datetime.fromtimestamp(
os.path.getmtime(old_path)
).strftime("%Y:%m:%d %H:%M:%S")
# 格式化日期
date_obj = datetime.strptime(date_str, "%Y:%m:%d %H:%M:%S")
new_name = f"{date_obj.strftime('%Y%m%d_%H%M%S')}_{filename}"
new_path = os.path.join(folder_path, new_name)
# 避免文件名冲突
counter = 1
while os.path.exists(new_path):
new_name = f"{date_obj.strftime('%Y%m%d_%H%M%S')}_{counter}_{filename}"
new_path = os.path.join(folder_path, new_name)
counter += 1
os.rename(old_path, new_path)
print(f"已重命名: {filename} -> {new_name}")
except Exception as e:
print(f"处理文件 {filename} 时出错: {e}")
# 使用示例(需要安装PIL库)
# pip install Pillow
batch_rename_by_date(r"D:\照片文件夹")
案例3:带前缀和分类的重命名
import os
import shutil
def batch_rename_with_category(folder_path, category_dict):
"""
带分类的批量重命名
category_dict: 包含类别和对应文件名前缀的字典
"""
# 创建分类文件夹
for category in category_dict.keys():
category_path = os.path.join(folder_path, category)
os.makedirs(category_path, exist_ok=True)
for filename in os.listdir(folder_path):
if os.path.isfile(os.path.join(folder_path, filename)):
file_path = os.path.join(folder_path, filename)
file_size = os.path.getsize(file_path)
ext = os.path.splitext(filename)[1].lower()
# 根据文件大小分类
if file_size > 5 * 1024 * 1024: # 大于5MB
category = "large"
elif file_size > 1 * 1024 * 1024: # 大于1MB
category = "medium"
else:
category = "small"
# 如果自定义分类包含了这个扩展名
for cat, exts in category_dict.items():
if ext in exts:
category = cat
break
# 新文件名
prefix = {
"large": "HQ",
"medium": "MED",
"small": "LQ"
}.get(category, "PHOTO")
new_name = f"{prefix}_{datetime.now().strftime('%Y%m%d')}_{filename}"
new_path = os.path.join(folder_path, category, new_name)
# 移动并重命名文件
shutil.move(file_path, new_path)
print(f"已处理: {filename} -> {category}/{new_name}")
# 使用示例
from datetime import datetime
categories = {
"风景": ['.jpg', '.jpeg', '.png'],
"人像": ['.bmp'],
"其他": ['.gif', '.tiff']
}
batch_rename_with_category(r"D:\照片文件夹", categories)
案例4:高级批量重命名(带GUI界面)
import os
import tkinter as tk
from tkinter import filedialog, messagebox, ttk
import threading
import glob
class PhotoRenamer:
def __init__(self, root):
self.root = root
self.root.title("批量照片重命名工具")
self.root.geometry("600x400")
# 变量
self.folder_path = tk.StringVar()
self.prefix = tk.StringVar(value="photo")
self.start_number = tk.IntVar(value=1)
self.date_format = tk.StringVar(value="%Y%m%d")
self.setup_ui()
def setup_ui(self):
# 文件夹选择
tk.Label(self.root, text="选择文件夹:").grid(row=0, column=0, padx=5, pady=5)
tk.Entry(self.root, textvariable=self.folder_path, width=40).grid(row=0, column=1, padx=5, pady=5)
tk.Button(self.root, text="浏览", command=self.browse_folder).grid(row=0, column=2, padx=5, pady=5)
# 前缀设置
tk.Label(self.root, text="文件名前缀:").grid(row=1, column=0, padx=5, pady=5)
tk.Entry(self.root, textvariable=self.prefix, width=20).grid(row=1, column=1, sticky="w", padx=5, pady=5)
# 起始编号
tk.Label(self.root, text="起始编号:").grid(row=2, column=0, padx=5, pady=5)
tk.Spinbox(self.root, from_=1, to=9999, textvariable=self.start_number, width=10).grid(row=2, column=1, sticky="w", padx=5, pady=5)
# 日期格式
tk.Label(self.root, text="日期格式:").grid(row=3, column=0, padx=5, pady=5)
format_combo = ttk.Combobox(self.root, textvariable=self.date_format,
values=["%Y%m%d", "%Y-%m-%d", "%Y%m%d_%H%M%S"])
format_combo.grid(row=3, column=1, sticky="w", padx=5, pady=5)
# 选项
self.use_exif = tk.BooleanVar(value=True)
tk.Checkbutton(self.root, text="使用EXIF日期", variable=self.use_exif).grid(row=4, column=0, columnspan=2, pady=10)
# 进度条
self.progress = ttk.Progressbar(self.root, length=400, mode='determinate')
self.progress.grid(row=5, column=0, columnspan=3, pady=10)
# 预览按钮
tk.Button(self.root, text="预览更改", command=self.preview_changes).grid(row=6, column=0, pady=10)
# 执行按钮
tk.Button(self.root, text="执行重命名", command=self.start_rename, bg="green", fg="white").grid(row=6, column=1, pady=10)
# 文本显示区
self.text_area = tk.Text(self.root, height=10, width=70)
self.text_area.grid(row=7, column=0, columnspan=3, padx=10, pady=10)
# 滚动条
scrollbar = tk.Scrollbar(self.root)
scrollbar.grid(row=7, column=3, sticky="ns")
self.text_area.config(yscrollcommand=scrollbar.set)
scrollbar.config(command=self.text_area.yview)
def browse_folder(self):
folder = filedialog.askdirectory()
if folder:
self.folder_path.set(folder)
def preview_changes(self):
"""预览更改"""
if not self.folder_path.get():
messagebox.showerror("错误", "请选择文件夹")
return
self.text_area.delete(1.0, tk.END)
self.text_area.insert(tk.END, "预览更改:\n\n")
image_files = self.get_image_files()
for i, old_path in enumerate(image_files, self.start_number.get()):
new_name = self.generate_new_name(old_path, i)
self.text_area.insert(tk.END, f"{os.path.basename(old_path)} -> {new_name}\n")
def get_image_files(self):
"""获取图片文件列表"""
image_extensions = ['*.jpg', '*.jpeg', '*.png', '*.gif', '*.bmp']
image_files = []
for ext in image_extensions:
image_files.extend(glob.glob(os.path.join(self.folder_path.get(), ext)))
return sorted(image_files)
def generate_new_name(self, old_path, index):
"""生成新文件名"""
ext = os.path.splitext(old_path)[1]
new_name = f"{self.prefix.get()}_{index:04d}{ext}"
return new_name
def start_rename(self):
"""开始重命名(在后台线程执行)"""
if not self.folder_path.get():
messagebox.showerror("错误", "请选择文件夹")
return
thread = threading.Thread(target=self.rename_files)
thread.start()
def rename_files(self):
"""执行重命名"""
image_files = self.get_image_files()
total = len(image_files)
self.progress['maximum'] = total
for i, old_path in enumerate(image_files, 1):
try:
new_name = self.generate_new_name(old_path, i)
new_path = os.path.join(self.folder_path.get(), new_name)
# 避免文件名冲突
counter = 1
while os.path.exists(new_path) and new_path != old_path:
new_name = f"{self.prefix.get()}_{i:04d}_{counter}{ext}"
new_path = os.path.join(self.folder_path.get(), new_name)
counter += 1
os.rename(old_path, new_path)
self.text_area.insert(tk.END, f"✓ {os.path.basename(old_path)} -> {new_name}\n")
except Exception as e:
self.text_area.insert(tk.END, f"✗ {os.path.basename(old_path)}: 错误 - {e}\n")
self.progress['value'] = i
self.root.update_idletasks()
messagebox.showinfo("完成", f"成功重命名 {total} 个文件!")
# 运行GUI程序
if __name__ == "__main__":
root = tk.Tk()
app = PhotoRenamer(root)
root.mainloop()
安装依赖
对于案例2和案例4,需要安装相应的库:
# 使用PIL读取EXIF信息 pip install Pillow # GUI和标准库(Python自带) # 无需额外安装
使用注意事项
- 备份重要文件:批量重命名操作不可逆,建议先备份
- 测试运行:先在小批量文件上测试
- 文件名冲突:代码中包含了冲突处理机制
- EXIF信息:并非所有照片都包含完整的EXIF信息
这些案例覆盖了从简单到复杂的不同需求,您可以根据实际场景选择合适的方案。