作为一名长期与文件管理打交道的开发者,我深知批量重命名目录的痛苦。每次整理下载的素材库、项目备份或者照片集时,手动修改几十上百个文件夹名称不仅耗时耗力,还容易出错。为了解决这个痛点,我决定开发一个基于PyQt5的图形化批量目录重命名工具。
这个工具的核心价值在于:
最初版本只支持单一操作(如添加前缀),但实际使用中发现以下典型场景:
于是我将架构升级为"规则流水线"模式,用户可自由组合多个操作步骤,系统会按顺序依次执行。这种设计带来了显著的效率提升,原本需要多次手动操作的任务现在可以一次性完成。
工具主要包含四大功能模块:
主窗口采用经典的垂直布局,分为三个主要区域:
python复制# 主布局结构
main_layout = QVBoxLayout()
# 1. 目录选择区域
dir_group = QGroupBox("目标目录")
dir_layout = QHBoxLayout()
# ...添加路径输入框和浏览按钮
main_layout.addWidget(dir_group)
# 2. 规则配置区域
rule_group = QGroupBox("规则设置")
rule_layout = QVBoxLayout()
# ...添加规则编辑器和规则列表
main_layout.addWidget(rule_group)
# 3. 操作区域
action_layout = QHBoxLayout()
# ...添加预览和执行按钮
main_layout.addLayout(action_layout)
规则处理是核心功能,采用链式设计模式:
python复制def apply_operations(self, original_name):
current_name = original_name
for rule in self.operations: # 按顺序应用每条规则
current_name = self.apply_single_rule(
rule['type'],
current_name,
rule['param1'],
rule['param2']
)
return current_name
def apply_single_rule(self, rule_type, name, p1, p2):
if rule_type == "prefix":
return f"{p1}{name}" if p1 else name
elif rule_type == "suffix":
return f"{name}{p1}" if p1 else name
elif rule_type == "replace":
return name.replace(p1, p2) if p1 else name
elif rule_type == "delete":
return name.replace(p1, "") if p1 else name
return name
为避免重命名过程中的常见问题,实现了多重保护:
python复制def is_valid_name(name):
invalid_chars = {'<', '>', ':', '"', '/', '\\', '|', '?', '*'}
return not any(char in invalid_chars for char in name)
python复制def check_conflicts(new_names):
from collections import defaultdict
count = defaultdict(int)
for name in new_names:
count[name] += 1
return {k:v for k,v in count.items() if v>1}
python复制def safe_rename(old, new):
temp = f"{old}.tmp{random.randint(1000,9999)}"
os.rename(old, temp) # 第一阶段:改为临时名
os.rename(temp, new) # 第二阶段:改为目标名
通过以下方式提升视觉体验:
python复制# 设置Fusion风格
QApplication.setStyle(QStyleFactory.create("Fusion"))
# 自定义样式表
self.setStyleSheet("""
QGroupBox {
border: 1px solid #e0e0e0;
border-radius: 5px;
margin-top: 10px;
}
QTableWidget {
alternate-background-color: #f5f5f5;
selection-background-color: #e3f2fd;
}
QPushButton {
min-width: 80px;
padding: 5px;
}
""")
使用Pillow将PNG转为ICO格式:
python复制from PIL import Image
img = Image.open('icon.png')
img.save('icon.ico', sizes=[(32,32), (48,48), (64,64)])
创建spec文件优化打包:
python复制# renamedir.spec
a = Analysis(['renamedir.py'],
pathex=['D:\\project'],
binaries=[],
datas=[('icon.ico', '.')],
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
name='renamedir',
debug=False,
strip=False,
upx=True,
runtime_tmpdir=None,
console=False,
icon='icon.ico')
bash复制pyinstaller --onefile --windowed --icon=icon.ico --add-data "icon.ico;." renamedir.py
原始目录结构:
code复制2023-07 旅行/
照片 001.jpg
照片 002.jpg
...
2023-08 聚会/
IMG_1234.jpg
IMG_1235.jpg
应用规则:
结果:
code复制2023-07_旅行_processed/
001.jpg
002.jpg
...
2023-08_聚会_processed/
1234.jpg
1235.jpg
原始状态:
code复制project_v1/
project_v2/
project_final/
project_really_final/
应用规则:
结果:
code复制20240615_1.0.0/
20240615_2.0.0/
20240615_final/
20240615_really_final/
python复制import re
def regex_replace(text, pattern, replacement):
return re.sub(pattern, replacement, text)
在实际开发过程中,有几个关键点值得注意:
提示:开发类似工具时,建议先从核心功能入手,再逐步添加辅助功能。过早追求完美可能导致项目难以完成。