如何用Python案例实现批量重命名照片?

wen python案例 2

本文目录导读:

如何用Python案例实现批量重命名照片?

  1. 案例1:基础批量重命名(按数字序号)
  2. 案例2:按拍摄日期重命名
  3. 案例3:带前缀和分类的重命名
  4. 案例4:高级批量重命名(带GUI界面)
  5. 安装依赖
  6. 使用注意事项

我来为您提供几个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自带)
# 无需额外安装

使用注意事项

  1. 备份重要文件:批量重命名操作不可逆,建议先备份
  2. 测试运行:先在小批量文件上测试
  3. 文件名冲突:代码中包含了冲突处理机制
  4. EXIF信息:并非所有照片都包含完整的EXIF信息

这些案例覆盖了从简单到复杂的不同需求,您可以根据实际场景选择合适的方案。

抱歉,评论功能暂时关闭!