原文地址:https://itxiaozhang.com/python-batch-rename-thousands-of-files/
如果您需要远程电脑维修或者编程开发,请加我微信咨询。
需求说明#
本案例需要开发一个用于批量文件重命名的 Python 程序,并可以进一步打包为 EXE,方便普通用户直接双击运行。
实际使用场景中,一个目录下可能存在几千、几万甚至更多文件。如果依靠人工逐个修改文件名,不仅效率较低,而且容易出现漏改、错改等问题,因此需要按照固定规则进行自动化批量处理。
程序放在 file 文件夹的同级目录,运行后自动处理 file 文件夹及其所有子文件夹中的文件。
只有同时满足以下条件的文件才会被纳入处理:
- 文件名以
YP 开头。 - 文件名中包含下划线
_。
不符合条件的文件不会修改,只会在日志中记录为跳过。
具体重命名规则如下:
- 将文件名开头的
YP 替换为 BG。 - 从文件名中的第一个下划线
_ 开始,删除下划线以及后面的所有描述内容。 - 保留原文件扩展名。
- 不修改文件内容。
- 不改变文件所在文件夹。
- 只修改文件名称,不修改文件夹名称。
例如:
1
| YP-LGGCZCB25-202512-TKY-008_Y幅第22跨湿接缝.pdf
|
修改为:
1
| BG-LGGCZCB25-202512-TKY-008.pdf
|
另一个示例:
1
| YP-LGGCZCB25-202512-TKY-013_Y幅第26跨横隔板及墩顶现浇连续段.pdf
|
修改为:
1
| BG-LGGCZCB25-202512-TKY-013.pdf
|
Excel 文件同样可以处理:
修改为:
程序本身不限制文件类型,因此 PDF、Word、Excel、图片、压缩包以及其他类型文件,都可以按照同一套规则处理。
程序设计#
程序使用 Python 开发,主要负责目录扫描、文件筛选、名称转换、安全检查、用户确认、正式重命名以及日志记录。
为了避免普通用户误操作,程序不会在启动后直接修改文件,而是按照以下流程执行:
- 获取程序所在目录。
- 查找程序同级目录下的
file 文件夹。 - 递归扫描
file 文件夹及全部子文件夹。 - 统计扫描到的文件总数。
- 筛选符合重命名条件的文件。
- 根据规则计算新的文件名。
- 显示完整的重命名预览。
- 检查目标文件名是否存在冲突。
- 检查目标文件是否已经存在。
- 用户输入
Y 后才允许执行。 - 正式执行前再次进行安全检查。
- 执行完成后生成日志。
程序的主流程代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
| def main() -> int:
args = parse_args()
app_dir = get_app_dir()
target_dir = get_target_dir(app_dir)
log_path = create_log_path(app_dir)
print_header(app_dir, target_dir)
if not target_dir.exists() or not target_dir.is_dir():
message = (
"未找到 file 文件夹,请确认程序和 file 文件夹"
f"放在同一级目录。当前查找位置:{target_dir}"
)
print("")
print(message)
empty_result = ScanResult(
total_count=0,
plan=[],
skipped=[]
)
write_log(
log_path,
app_dir,
target_dir,
empty_result,
"失败",
[message]
)
return finish(args, log_path, 1)
scan_result = scan_files(target_dir)
print_preview(scan_result, app_dir)
if not scan_result.plan:
message = (
"没有找到以 YP 开头且包含下划线 _ 的文件,"
"本次没有修改任何文件。"
)
print("")
print(message)
write_log(
log_path,
app_dir,
target_dir,
scan_result,
"未执行",
[message]
)
return finish(args, log_path, 0)
errors = validate_plan(scan_result.plan)
if errors:
print("")
print("发现风险,已停止。不会修改任何文件。")
for error in errors:
print(f"- {error}")
write_log(
log_path,
app_dir,
target_dir,
scan_result,
"失败",
errors
)
return finish(args, log_path, 1)
should_execute = args.execute
if args.preview:
should_execute = False
elif not args.execute:
print("")
print("请仔细核对上面的预览。")
answer = input(
"确认执行重命名请输入 Y,输入其他内容则取消:"
).strip().casefold()
should_execute = answer == "y"
if not should_execute:
message = "用户未确认执行,本次没有修改任何文件。"
print("")
print(message)
write_log(
log_path,
app_dir,
target_dir,
scan_result,
"未执行",
[message]
)
return finish(args, log_path, 0)
latest_errors = validate_plan(scan_result.plan)
if latest_errors:
print("")
print("执行前再次检查发现风险,已停止。不会修改任何文件。")
for error in latest_errors:
print(f"- {error}")
write_log(
log_path,
app_dir,
target_dir,
scan_result,
"失败",
latest_errors
)
return finish(args, log_path, 1)
try:
rename_files(scan_result.plan)
except Exception as exc:
message = f"执行过程中失败:{exc}"
print("")
print(message)
write_log(
log_path,
app_dir,
target_dir,
scan_result,
"失败",
[message]
)
return finish(args, log_path, 1)
message = (
f"重命名完成,成功处理 {len(scan_result.plan)} 个文件。"
)
print("")
print(message)
write_log(
log_path,
app_dir,
target_dir,
scan_result,
"成功",
[message]
)
return finish(args, log_path, 0)
if __name__ == "__main__":
raise SystemExit(main())
|
这部分代码主要负责整个程序的运行流程,具体的目录扫描、名称生成、安全检查和日志写入,则由 scan_files()、validate_plan()、rename_files() 和 write_log() 等函数分别完成。
其中最关键的是正式执行前的两次安全检查。
第一次检查发生在显示预览之后:
1
2
3
4
5
6
7
8
9
10
| errors = validate_plan(scan_result.plan)
if errors:
print("")
print("发现风险,已停止。不会修改任何文件。")
for error in errors:
print(f"- {error}")
return finish(args, log_path, 1)
|
如果检测到文件名冲突、目标文件已经存在或者其他风险,程序直接终止,不修改任何文件。
用户确认之后,正式重命名前还会再次检查:
1
2
3
4
5
6
7
8
9
10
| latest_errors = validate_plan(scan_result.plan)
if latest_errors:
print("")
print("执行前再次检查发现风险,已停止。不会修改任何文件。")
for error in latest_errors:
print(f"- {error}")
return finish(args, log_path, 1)
|
这样可以避免用户查看预览之后,文件目录发生变化而造成覆盖或冲突。
正式重命名部分也进行了异常捕获:
1
2
3
4
5
| try:
rename_files(scan_result.plan)
except Exception as exc:
message = f"执行过程中失败:{exc}"
print(message)
|
如果执行过程中出现异常,可以停止当前流程并将具体原因记录到日志中,方便后续检查。
安全机制#
批量修改文件名称具有一定风险,因此程序的设计重点之一是避免误修改和文件覆盖。
如果没有找到 file 文件夹,程序会提示:
1
| 未找到 file 文件夹,请确认程序和 file 文件夹放在同一级目录。
|
并直接停止运行。
如果扫描完成后没有发现符合条件的文件,则提示:
1
| 没有找到以 YP 开头且包含下划线 _ 的文件,本次没有修改任何文件。
|
同样不会执行任何修改。
对于已经生成的重命名计划,程序还会通过:
1
| validate_plan(scan_result.plan)
|
检查潜在风险。
主要包括:
- 多个文件是否会生成相同的新文件名。
- 新文件名对应的目标文件是否已经存在。
- 当前重命名计划是否存在其他冲突。
一旦发现风险,程序会显示:
只有所有检查全部通过后,才会进入人工确认阶段。
程序随后提示:
1
2
| 请仔细核对上面的预览。
确认执行重命名请输入 Y,输入其他内容则取消:
|
只有用户明确输入:
并按回车键后,程序才执行正式重命名。
输入其他内容则提示:
因此程序默认行为始终是先预览、再确认,而不是直接修改文件。
使用方法与运行结果#
程序打包为 EXE 后,普通用户不需要安装 Python,也不需要编辑代码。
程序和文件目录可以按照以下结构放置:
1
2
3
4
5
6
7
8
9
10
| 程序目录
├─ rename_files.exe
├─ file
│ ├─ 文件1.pdf
│ ├─ 文件2.xlsx
│ ├─ 文件3.zip
│ └─ 子文件夹
│ ├─ 文件4.pdf
│ └─ 文件5.docx
└─ logs
|
需要批量重命名的文件放入 file 文件夹即可。
文件也可以继续放在不同的子文件夹中,程序会递归扫描这些目录。
双击 EXE 后,程序首先扫描全部文件,并生成重命名预览。
例如:
1
2
3
4
5
6
7
| YP-LGGCZCB25-202512-TKY-008_Y幅第22跨湿接缝.pdf
->
BG-LGGCZCB25-202512-TKY-008.pdf
YP-LGGCZCB25-202512-TKY-013_Y幅第26跨横隔板及墩顶现浇连续段.pdf
->
BG-LGGCZCB25-202512-TKY-013.pdf
|
确认所有预览结果正确后输入:
程序开始执行批量重命名。
完成后提示:
演示过程中使用了 20 个文件进行测试,可以较直观地检查处理结果。
当文件数量只有几十个时,人工修改仍然可以完成,但实际文件数量达到几千、几万甚至更多后,自动化程序的优势会更加明显。
程序无需根据 PDF、Excel、Word 或图片分别编写规则,因为此次操作只涉及文件名,不修改文件内部数据,因此可以统一处理不同扩展名的文件。
日志记录#
每次启动程序都会生成对应的运行日志。
日志统一保存在程序同级目录的:
文件夹中。
日志主要记录以下信息:
- 本次程序运行时间。
file 文件夹的实际路径。- 扫描到的文件总数。
- 符合规则、准备重命名的文件数量。
- 被跳过的文件数量。
- 每个文件修改前和修改后的名称。
- 正式执行成功后的处理数量。
- 用户取消操作时的状态。
- 仅进行预览时的状态。
- 执行失败时的具体原因。
例如日志中的重命名记录可以采用:
1
2
3
| YP-LGGCZCB25-202512-TKY-008_Y幅第22跨湿接缝.pdf
->
BG-LGGCZCB25-202512-TKY-008.pdf
|
这种形式。
文件数量较少时,可以直接查看目录确认结果。
但如果一次处理几千甚至数万个文件,逐个检查已经不现实,此时完整的重命名日志可以用于核对哪些文件被修改、哪些文件被跳过,以及每个文件具体从什么名称修改为什么名称。
实现效果#
该程序使用 Python 实现批量文件扫描和重命名,并可以进一步通过 PyInstaller 等工具打包为独立 EXE。
对于普通用户,实际操作过程只需要:
1
2
3
4
5
6
7
8
9
10
11
| 准备 file 文件夹
↓
双击 EXE
↓
查看重命名预览
↓
输入 Y
↓
完成批量重命名
↓
查看日志
|
程序同时考虑了递归扫描、大批量文件处理、目标文件冲突、文件覆盖风险、用户误操作以及日志追踪等问题。
核心重命名规则本身并不复杂,真正需要重点处理的是大量文件情况下的安全性、稳定性以及普通用户的使用体验。
通过自动扫描、预览、风险检查、人工确认、再次检查和日志记录,可以在处理大批量文件时减少重复人工操作,同时降低批量误修改文件名的风险。
视频版本#