背景介绍
你是否曾面对几十个甚至上百个文件,需要手动修改名称?比如旅行照片要统一加上日期前缀,工作文档要按序号排列,手动重命名不仅耗时还容易出错。今天,我们将用Python和Tkinter打造一个轻量级批量重命名工具,支持灵活规则配置、实时预览和一键执行,彻底解决这个痛点。
思路分析
要实现这个工具,我们需要拆解核心功能并对应技术方案:
1. 文件夹选择:用Tkinter的filedialog弹出文件夹选择对话框;
2. 规则配置:通过输入框和复选框收集用户设置(前缀/后缀、序号、替换、日期);
3. 预览功能:遍历文件夹文件,根据规则生成新名称,用列表框展示对比结果;
4. 执行重命名:调用os.rename批量修改文件名,捕获异常统计成功率;
5. 结果反馈:用messagebox显示成功/失败数量及详情。
代码实现
我们选择Tkinter作为GUI框架(内置无需额外安装),结合os处理文件系统、datetime处理日期。以下是完整可运行代码:
import tkinter as tk
from tkinter import filedialog, messagebox
import os
from datetime import datetime
# 全局变量存储预览结果(原路径, 新路径)
preview_list = []
def select_folder():
"""选择目标文件夹"""
folder = filedialog.askdirectory()
if folder:
entry_folder.delete(0, tk.END)
entry_folder.insert(0, folder)
def preview():
"""生成重命名预览结果"""
global preview_list
preview_list.clear()
list_preview.delete(0, tk.END)
folder_path = entry_folder.get().strip()
if not folder_path or not os.path.isdir(folder_path):
messagebox.showwarning("警告", "请选择有效的文件夹!")
return
# 获取规则参数
prefix = entry_prefix.get().strip()
suffix = entry_suffix.get().strip()
try:
seq_start = int(entry_seq_start.get().strip())
seq_digits = int(entry_seq_digits.get().strip())
except ValueError:
messagebox.showwarning("警告", "序号起始和位数必须为整数!")
return
keep_name = var_keep_name.get()
use_replace = var_replace.get()
old_str = entry_old_str.get().strip()
new_str = entry_new_str.get().strip()
use_date = var_date.get()
date_format = entry_date_format.get().strip() if use_date else ""
# 遍历文件夹中的文件(排除子文件夹)
files = [f for f in os.listdir(folder_path) if os.path.isfile(os.path.join(folder_path, f))]
if not files:
messagebox.showinfo("提示", "文件夹中无文件!")
return
files.sort() # 按文件名排序
seq_num = seq_start
for filename in files:
name, ext = os.path.splitext(filename)
date_part = ""
# 处理日期插入
if use_date:
try:
date_part = datetime.now().strftime(date_format)
except Exception as e:
messagebox.showwarning("警告", f"日期格式错误:{str(e)}")
return
# 处理名称部分(原文件名/序号)
name_part = ""
if keep_name:
temp_name = name
if use_replace and old_str:
temp_name = temp_name.replace(old_str, new_str)
name_part = temp_name
else:
name_part = str(seq_num).zfill(seq_digits)
# 组合新文件名
new_filename = f"{prefix}{date_part}{name_part}{suffix}{ext}"
if not new_filename:
messagebox.showwarning("警告", f"生成空文件名:{filename}")
continue
# 构建路径
old_path = os.path.join(folder_path, filename)
new_path = os.path.join(folder_path, new_filename)
preview_list.append((old_path, new_path))
list_preview.insert(tk.END, f"{filename} → {new_filename}")
seq_num +=1
messagebox.showinfo("提示", f"预览完成,共{len(files)}个文件")
def execute_rename():
"""执行批量重命名"""
if not preview_list:
messagebox.showwarning("警告", "请先预览结果!")
return
if not messagebox.askyesno("确认", "确定执行?此操作不可撤销!"):
return
success = 0
fail = 0
fail_details = []
for old_path, new_path in preview_list:
try:
os.rename(old_path, new_path)
success +=1
except Exception as e:
fail +=1
fail_details.append(f"{os.path.basename(old_path)}: {str(e)}")
# 显示结果
result = f"成功:{success} | 失败:{fail}\n"
if fail >0:
result += "失败详情:\n" + "\n".join(fail_details)
messagebox.showinfo("结果", result)
preview() # 刷新预览
# -------------------------- 主界面构建 --------------------------
root = tk.Tk()
root.title("批量文件重命名工具")
root.geometry("850x650")
# 文件夹选择区域
tk.Label(root, text="目标文件夹:").grid(row=0, column=0, padx=5, pady=5, sticky="w")
entry_folder = tk.Entry(root, width=70)
entry_folder.grid(row=0, column=1, padx=5, pady=5, sticky="we")
tk.Button(root, text="选择", command=select_folder).grid(row=0, column=2, padx=5, pady=5)
# 规则配置区域
# 前缀/后缀
tk.Label(root, text="前缀:").grid(row=1, column=0, padx=5, pady=5, sticky="w")
entry_prefix = tk.Entry(root, width=20)
entry_prefix.grid(row=1, column=1, padx=5, pady=5, sticky="w")
tk.Label(root, text="后缀:").grid(row=1, column=2, padx=5, pady=5, sticky="w")
entry_suffix = tk.Entry(root, width=20)
entry_suffix.grid(row=1, column=3, padx=5, pady=5, sticky="w")
# 序号设置
tk.Label(root, text="序号起始:").grid(row=2, column=0, padx=5, pady=5, sticky="w")
entry_seq_start = tk.Entry(root, width=5)
entry_seq_start.grid(row=2, column=1, padx=5, pady=5, sticky="w")
entry_seq_start.insert(0, "1")
tk.Label(root, text="序号位数:").grid(row=2, column=2, padx=5, pady=5, sticky="w")
entry_seq_digits = tk.Entry(root, width=5)
entry_seq_digits.grid(row=2, column=3, padx=5, pady=5, sticky="w")
entry_seq_digits.insert(0, "3")
# 保留原文件名
var_keep_name = tk.BooleanVar()
tk.Checkbutton(root, text="保留原文件名(不含后缀)", variable=var_keep_name).grid(row=3, column=0, padx=5, pady=5, sticky="w", columnspan=2)
# 字符串替换
var_replace = tk.BooleanVar()
tk.Checkbutton(root, text="字符串替换", variable=var_replace).grid(row=4, column=0, padx=5, pady=5, sticky="w")
tk.Label(root, text="旧字符串:").grid(row=4, column=1, padx=5, pady=5, sticky="w")
entry_old_str = tk.Entry(root, width=20)
entry_old_str.grid(row=4, column=2, padx=5, pady=5, sticky="w")
tk.Label(root, text="新字符串:").grid(row=4, column=3, padx=5, pady=5, sticky="w")
entry_new_str = tk.Entry(root, width=20)
entry_new_str.grid(row=4, column=4, padx=5, pady=5, sticky="w")
# 日期插入
var_date = tk.BooleanVar()
tk.Checkbutton(root, text="插入日期", variable=var_date).grid(row=5, column=0, padx=5, pady=5, sticky="w")
tk.Label(root, text="日期格式(如%Y-%m-%d):").grid(row=5, column=1, padx=5, pady=5, sticky="w")
entry_date_format = tk.Entry(root, width=20)
entry_date_format.grid(row=5, column=2, padx=5, pady=5, sticky="w")
entry_date_format.insert(0, "%Y-%m-%d")
# 预览区域
tk.Button(root, text="预览结果", command=preview).grid(row=6, column=0, padx=5, pady=10, sticky="w")
list_preview = tk.Listbox(root, width=100, height=18)
list_preview.grid(row=7, column=0, padx=5, pady=5, columnspan=5, sticky="we")
scrollbar = tk.Scrollbar(root, orient="vertical", command=list_preview.yview)
scrollbar.grid(row=7, column=5, sticky="ns")
list_preview.config(yscrollcommand=scrollbar.set)
# 执行按钮
tk.Button(root, text="执行重命名", command=execute_rename, bg="#4CAF50", fg="white", padx=10, pady=5).grid(row=8, column=0, padx=5, pady=10, sticky="w")
root.mainloop()
代码解释
- 界面构建:使用Tkinter的
grid布局组织组件,包括文件夹选择区、规则配置区、预览区和执行按钮。 - 文件夹选择:通过
filedialog.askdirectory获取用户选择的文件夹路径。 - 规则处理:
- 前缀/后缀:直接拼接在名称前后;
- 序号:支持起始值和补零位数;
- 保留原文件名:可选是否保留原名称(不含后缀);
- 字符串替换:对原文件名进行指定字符串替换;
- 日期插入:用
datetime生成指定格式的日期字符串。
- 预览功能:遍历文件夹文件,根据规则生成新名称并展示对比结果,避免误操作。
- 执行重命名:调用
os.rename批量修改文件,捕获异常并统计结果。
总结
这个工具通过简单的GUI界面实现了灵活的批量重命名功能,涵盖了文件操作、字符串处理和事件驱动编程等核心知识点。你可以基于此扩展更多功能:
– 支持正则表达式替换;
– 自定义规则顺序;
– 保存/加载常用规则;
– 处理子文件夹中的文件。
希望这个工具能帮你节省时间,也希望你能从代码中学到实用的Python技能!
“`