添加Windows工具,以及分类。
This commit is contained in:
BIN
Windows/批量重命名/BatchRenameTool.exe
Normal file
BIN
Windows/批量重命名/BatchRenameTool.exe
Normal file
Binary file not shown.
324
Windows/批量重命名/BatchRenameTool.py
Normal file
324
Windows/批量重命名/BatchRenameTool.py
Normal file
@@ -0,0 +1,324 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
批量文件重命名工具
|
||||
支持添加文件,按顺序重命名
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import tkinter as tk
|
||||
from tkinter import Label, Button, Entry, messagebox, Frame, Scrollbar, Listbox, VERTICAL, HORIZONTAL, END, filedialog
|
||||
|
||||
class BatchRenameApp:
|
||||
def __init__(self, root):
|
||||
self.root = root
|
||||
self.root.title("批量文件重命名工具")
|
||||
self.root.geometry("750x800")
|
||||
self.root.resizable(True, True)
|
||||
|
||||
# 初始化变量
|
||||
self.file_list = []
|
||||
self.new_prefix = "renamed"
|
||||
self.start_number = 1
|
||||
self.number_digits = 3
|
||||
|
||||
# 创建界面
|
||||
self.create_widgets()
|
||||
|
||||
def create_widgets(self):
|
||||
# 主框架
|
||||
main_frame = Frame(self.root, padx=20, pady=20)
|
||||
main_frame.pack(fill="both", expand=True)
|
||||
|
||||
# 提示区域
|
||||
drop_frame = Frame(main_frame, pady=10, bg="#E3F2FD", relief="solid", bd=2)
|
||||
drop_frame.pack(fill="x")
|
||||
|
||||
self.drop_label = Label(drop_frame, text='📁 点击下方"添加文件"按钮选择文件',
|
||||
font=("SimHei", 14, "bold"), bg="#E3F2FD", fg="#1976D2",
|
||||
height=2)
|
||||
self.drop_label.pack(fill="x", expand=True)
|
||||
|
||||
# 按钮区域
|
||||
btn_frame = Frame(main_frame, pady=10)
|
||||
btn_frame.pack(fill="x")
|
||||
|
||||
Button(btn_frame, text="添加文件", command=self.add_files, font=("SimHei", 10), width=12).pack(side="left", padx=5)
|
||||
Button(btn_frame, text="清空列表", command=self.clear_list, font=("SimHei", 10), width=12).pack(side="left", padx=5)
|
||||
Button(btn_frame, text="上移", command=self.move_up, font=("SimHei", 10), width=8).pack(side="left", padx=5)
|
||||
Button(btn_frame, text="下移", command=self.move_down, font=("SimHei", 10), width=8).pack(side="left", padx=5)
|
||||
Button(btn_frame, text="移除选中", command=self.remove_selected, font=("SimHei", 10), width=10).pack(side="left", padx=5)
|
||||
|
||||
# 文件列表
|
||||
list_frame = Frame(main_frame, pady=10)
|
||||
list_frame.pack(fill="both", expand=True)
|
||||
|
||||
Label(list_frame, text="文件列表 (按顺序重命名):", font=("SimHei", 10, "bold")).pack(anchor="w")
|
||||
|
||||
# 列表框容器
|
||||
list_container = Frame(list_frame)
|
||||
list_container.pack(fill="both", expand=True, pady=5)
|
||||
|
||||
# 文件列表
|
||||
self.file_listbox = Listbox(list_container, width=80, height=12, selectmode="single")
|
||||
self.file_listbox.pack(side="left", fill="both", expand=True)
|
||||
|
||||
# 垂直滚动条
|
||||
vscrollbar = Scrollbar(list_container, orient=VERTICAL, command=self.file_listbox.yview)
|
||||
vscrollbar.pack(side="right", fill="y")
|
||||
self.file_listbox.config(yscrollcommand=vscrollbar.set)
|
||||
|
||||
# 水平滚动条
|
||||
hscrollbar = Scrollbar(list_container, orient=HORIZONTAL, command=self.file_listbox.xview)
|
||||
hscrollbar.pack(side="bottom", fill="x")
|
||||
self.file_listbox.config(xscrollcommand=hscrollbar.set)
|
||||
|
||||
# 重命名设置
|
||||
settings_frame = Frame(main_frame, pady=10)
|
||||
settings_frame.pack(fill="x")
|
||||
|
||||
Label(settings_frame, text="重命名设置:", font=("SimHei", 10, "bold")).pack(anchor="w")
|
||||
|
||||
# 前缀
|
||||
prefix_frame = Frame(settings_frame)
|
||||
prefix_frame.pack(fill="x", pady=5)
|
||||
|
||||
Label(prefix_frame, text="新名称前缀:", width=15).pack(side="left", padx=5)
|
||||
self.prefix_entry = Entry(prefix_frame, width=40)
|
||||
self.prefix_entry.insert(0, self.new_prefix)
|
||||
self.prefix_entry.pack(side="left", padx=5)
|
||||
|
||||
# 起始编号
|
||||
start_frame = Frame(settings_frame)
|
||||
start_frame.pack(fill="x", pady=5)
|
||||
|
||||
Label(start_frame, text="起始编号:", width=15).pack(side="left", padx=5)
|
||||
self.start_entry = Entry(start_frame, width=10)
|
||||
self.start_entry.insert(0, str(self.start_number))
|
||||
self.start_entry.pack(side="left", padx=5)
|
||||
|
||||
# 编号位数
|
||||
digits_frame = Frame(settings_frame)
|
||||
digits_frame.pack(fill="x", pady=5)
|
||||
|
||||
Label(digits_frame, text="编号位数:", width=15).pack(side="left", padx=5)
|
||||
self.digits_entry = Entry(digits_frame, width=10)
|
||||
self.digits_entry.insert(0, str(self.number_digits))
|
||||
self.digits_entry.pack(side="left", padx=5)
|
||||
Label(digits_frame, text="(例如: 3位 = 001, 002...)").pack(side="left", padx=5)
|
||||
|
||||
# 执行按钮
|
||||
button_frame = Frame(main_frame, pady=15)
|
||||
button_frame.pack(fill="x")
|
||||
|
||||
Button(button_frame, text="预览重命名", command=self.preview_rename, font=("SimHei", 11), width=15).pack(side="left", padx=10)
|
||||
Button(button_frame, text="执行重命名", command=self.execute_rename, font=("SimHei", 11, "bold"), width=15, bg="#4CAF50", fg="white").pack(side="left", padx=10)
|
||||
|
||||
# 结果显示
|
||||
result_frame = Frame(main_frame, pady=10)
|
||||
result_frame.pack(fill="both", expand=True)
|
||||
|
||||
Label(result_frame, text="重命名结果:", font=("SimHei", 10, "bold")).pack(anchor="w")
|
||||
|
||||
# 结果列表
|
||||
result_container = Frame(result_frame)
|
||||
result_container.pack(fill="both", expand=True)
|
||||
|
||||
self.result_listbox = Listbox(result_container, width=80, height=8)
|
||||
self.result_listbox.pack(side="left", fill="both", expand=True)
|
||||
|
||||
# 垂直滚动条
|
||||
rvscrollbar = Scrollbar(result_container, orient=VERTICAL, command=self.result_listbox.yview)
|
||||
rvscrollbar.pack(side="right", fill="y")
|
||||
self.result_listbox.config(yscrollcommand=rvscrollbar.set)
|
||||
|
||||
# 水平滚动条
|
||||
rhscrollbar = Scrollbar(result_container, orient=HORIZONTAL, command=self.result_listbox.xview)
|
||||
rhscrollbar.pack(side="bottom", fill="x")
|
||||
self.result_listbox.config(xscrollcommand=rhscrollbar.set)
|
||||
|
||||
def add_files(self):
|
||||
"""通过对话框添加文件"""
|
||||
files = filedialog.askopenfilenames(title="选择文件")
|
||||
if files:
|
||||
for file_path in files:
|
||||
if file_path not in self.file_list:
|
||||
self.file_list.append(file_path)
|
||||
file_name = os.path.basename(file_path)
|
||||
self.file_listbox.insert(END, f"{len(self.file_list)}. {file_name}")
|
||||
|
||||
self.drop_label.config(text=f"📁 已添加 {len(self.file_list)} 个文件")
|
||||
|
||||
def clear_list(self):
|
||||
"""清空文件列表"""
|
||||
self.file_list.clear()
|
||||
self.file_listbox.delete(0, END)
|
||||
self.drop_label.config(text='📁 点击下方"添加文件"按钮选择文件')
|
||||
|
||||
def move_up(self):
|
||||
"""上移选中的文件"""
|
||||
selection = self.file_listbox.curselection()
|
||||
if not selection:
|
||||
return
|
||||
|
||||
index = selection[0]
|
||||
if index == 0:
|
||||
return
|
||||
|
||||
# 交换列表中的位置
|
||||
self.file_list[index], self.file_list[index-1] = self.file_list[index-1], self.file_list[index]
|
||||
|
||||
# 更新显示
|
||||
self.refresh_listbox()
|
||||
self.file_listbox.selection_set(index-1)
|
||||
|
||||
def move_down(self):
|
||||
"""下移选中的文件"""
|
||||
selection = self.file_listbox.curselection()
|
||||
if not selection:
|
||||
return
|
||||
|
||||
index = selection[0]
|
||||
if index == len(self.file_list) - 1:
|
||||
return
|
||||
|
||||
# 交换列表中的位置
|
||||
self.file_list[index], self.file_list[index+1] = self.file_list[index+1], self.file_list[index]
|
||||
|
||||
# 更新显示
|
||||
self.refresh_listbox()
|
||||
self.file_listbox.selection_set(index+1)
|
||||
|
||||
def remove_selected(self):
|
||||
"""移除选中的文件"""
|
||||
selection = self.file_listbox.curselection()
|
||||
if not selection:
|
||||
return
|
||||
|
||||
index = selection[0]
|
||||
self.file_list.pop(index)
|
||||
self.refresh_listbox()
|
||||
|
||||
if self.file_list:
|
||||
self.drop_label.config(text=f"📁 已添加 {len(self.file_list)} 个文件")
|
||||
else:
|
||||
self.drop_label.config(text='📁 点击下方"添加文件"按钮选择文件')
|
||||
|
||||
def refresh_listbox(self):
|
||||
"""刷新列表框显示"""
|
||||
self.file_listbox.delete(0, END)
|
||||
for i, file_path in enumerate(self.file_list, 1):
|
||||
file_name = os.path.basename(file_path)
|
||||
self.file_listbox.insert(END, f"{i}. {file_name}")
|
||||
|
||||
def format_number(self, num, digits):
|
||||
"""格式化数字,添加前导零"""
|
||||
return str(num).zfill(digits)
|
||||
|
||||
def preview_rename(self):
|
||||
"""预览重命名操作"""
|
||||
if not self.file_list:
|
||||
messagebox.showinfo("提示", "文件列表为空")
|
||||
return
|
||||
|
||||
self.new_prefix = self.prefix_entry.get().strip()
|
||||
|
||||
try:
|
||||
self.start_number = int(self.start_entry.get().strip())
|
||||
self.number_digits = int(self.digits_entry.get().strip())
|
||||
|
||||
if self.start_number < 0:
|
||||
raise ValueError("起始编号不能为负数")
|
||||
if self.number_digits < 1:
|
||||
raise ValueError("编号位数必须大于0")
|
||||
except ValueError as e:
|
||||
messagebox.showerror("错误", f"参数设置错误: {e}")
|
||||
return
|
||||
|
||||
# 清空结果列表
|
||||
self.result_listbox.delete(0, END)
|
||||
|
||||
current_num = self.start_number
|
||||
|
||||
for file_path in self.file_list:
|
||||
old_name = os.path.basename(file_path)
|
||||
ext = os.path.splitext(old_name)[1]
|
||||
formatted_num = self.format_number(current_num, self.number_digits)
|
||||
new_name = f"{self.new_prefix}{formatted_num}{ext}"
|
||||
|
||||
self.result_listbox.insert(END, f"{old_name} -> {new_name}")
|
||||
current_num += 1
|
||||
|
||||
messagebox.showinfo("预览", f"预览完成!\n共 {len(self.file_list)} 个文件将被重命名")
|
||||
|
||||
def execute_rename(self):
|
||||
"""执行重命名操作"""
|
||||
if not self.file_list:
|
||||
messagebox.showinfo("提示", "文件列表为空")
|
||||
return
|
||||
|
||||
self.new_prefix = self.prefix_entry.get().strip()
|
||||
|
||||
try:
|
||||
self.start_number = int(self.start_entry.get().strip())
|
||||
self.number_digits = int(self.digits_entry.get().strip())
|
||||
|
||||
if self.start_number < 0:
|
||||
raise ValueError("起始编号不能为负数")
|
||||
if self.number_digits < 1:
|
||||
raise ValueError("编号位数必须大于0")
|
||||
except ValueError as e:
|
||||
messagebox.showerror("错误", f"参数设置错误: {e}")
|
||||
return
|
||||
|
||||
# 确认操作
|
||||
confirm = messagebox.askyesno("确认", f"确定要重命名 {len(self.file_list)} 个文件吗?")
|
||||
if not confirm:
|
||||
return
|
||||
|
||||
# 清空结果列表
|
||||
self.result_listbox.delete(0, END)
|
||||
|
||||
success_count = 0
|
||||
skip_count = 0
|
||||
current_num = self.start_number
|
||||
|
||||
for file_path in self.file_list:
|
||||
old_name = os.path.basename(file_path)
|
||||
ext = os.path.splitext(old_name)[1]
|
||||
formatted_num = self.format_number(current_num, self.number_digits)
|
||||
new_name = f"{self.new_prefix}{formatted_num}{ext}"
|
||||
|
||||
# 获取文件所在目录
|
||||
dir_path = os.path.dirname(file_path)
|
||||
new_path = os.path.join(dir_path, new_name)
|
||||
|
||||
if os.path.exists(new_path):
|
||||
if old_name.lower() != new_name.lower():
|
||||
self.result_listbox.insert(END, f"[跳过] 目标已存在: {new_name}")
|
||||
skip_count += 1
|
||||
else:
|
||||
try:
|
||||
os.rename(file_path, new_path)
|
||||
self.result_listbox.insert(END, f"[成功] {old_name} -> {new_name}")
|
||||
success_count += 1
|
||||
except Exception as e:
|
||||
self.result_listbox.insert(END, f"[失败] {old_name} - {e}")
|
||||
skip_count += 1
|
||||
|
||||
current_num += 1
|
||||
|
||||
messagebox.showinfo("完成", f"重命名完成!\n成功: {success_count} 个\n失败/跳过: {skip_count} 个")
|
||||
|
||||
# 清空列表
|
||||
self.clear_list()
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
root = tk.Tk()
|
||||
app = BatchRenameApp(root)
|
||||
root.mainloop()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
65
Windows/批量重命名/使用说明.md
Normal file
65
Windows/批量重命名/使用说明.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# 批量文件重命名工具 - 使用指南
|
||||
|
||||
## 工具简介
|
||||
|
||||
批量文件重命名工具是一款简洁高效的 Windows 桌面应用程序,支持快速对多个文件按顺序进行重命名操作。
|
||||
|
||||
## 运行方式
|
||||
|
||||
双击 `BatchRenameTool.exe` 直接运行,或使用 Python 3 运行 `BatchRenameTool.py`。
|
||||
|
||||
## 主要功能
|
||||
|
||||
| 功能 | 说明 |
|
||||
|------|------|
|
||||
| 添加文件 | 支持选择多个文件添加到列表 |
|
||||
| 文件排序 | 通过上移/下移调整文件重命名顺序 |
|
||||
| 自定义前缀 | 可设置新文件名的前缀 |
|
||||
| 起始编号 | 支持设置起始数字 |
|
||||
| 编号位数 | 可自定义编号位数(如3位:001, 002...) |
|
||||
| 预览功能 | 执行前可预览所有文件的命名结果 |
|
||||
| 重命名执行 | 一键批量重命名文件 |
|
||||
|
||||
## 使用步骤
|
||||
|
||||
### 1. 添加文件
|
||||
点击「添加文件」按钮,在弹出的文件选择对话框中选择需要重命名的文件。支持多选。
|
||||
|
||||
### 2. 调整顺序
|
||||
- 选择列表中的文件
|
||||
- 点击「上移」或「下移」调整其在重命名序列中的位置
|
||||
- 点击「移除选中」可删除不想重命名的文件
|
||||
|
||||
### 3. 设置参数
|
||||
- **新名称前缀**:输入新文件名的前缀部分(默认为 `renamed`)
|
||||
- **起始编号**:设置编号的起始数字(默认为 1)
|
||||
- **编号位数**:设置编号的总位数,如设为 3 则显示为 001、002(默认为 3)
|
||||
|
||||
### 4. 预览
|
||||
点击「预览重命名」按钮,查看所有文件的重命名结果,确认无误后再执行。
|
||||
|
||||
### 5. 执行
|
||||
点击绿色的「执行重命名」按钮,确认后开始重命名。
|
||||
|
||||
## 示例
|
||||
|
||||
假设有以下文件:
|
||||
- `photo.jpg`
|
||||
- `image.png`
|
||||
- `picture.bmp`
|
||||
|
||||
设置参数:
|
||||
- 前缀:`photo_`
|
||||
- 起始编号:`1`
|
||||
- 编号位数:`2`
|
||||
|
||||
预览/执行结果:
|
||||
- `photo.jpg` → `photo_01.jpg`
|
||||
- `image.png` → `photo_02.png`
|
||||
- `picture.bmp` → `photo_03.bmp`
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. 执行重命名会直接修改文件系统,无法通过撤销恢复,请务必先使用预览功能确认
|
||||
2. 如果目标文件名已存在,该文件会被跳过
|
||||
3. 编号位数设置过小可能导致编号溢出(如 100+ 个文件但只设 2 位数)
|
||||
Reference in New Issue
Block a user