用批处理实现文件夹批量加密压缩,自动生成随机密码
前言
最近有个需求:手头有一堆文件夹需要逐个加密压缩,每个还要用不同的密码。手动一个一个来太折磨人了,于是想写个批处理一键搞定。
折腾过程中踩了不少坑,特别是批处理里那些转义字符和延迟扩展的坑,今天把最终方案分享出来。
需求分析
我需要这样一个小工具:
- 遍历当前目录下的所有子文件夹
- 每个文件夹自动生成一个随机密码
- 用该密码加密压缩成 ZIP
- 同时生成一个密码文件方便日后查找
原始脚本是从一个 password.txt 文件读取密码的,但手动准备密码文件太麻烦,于是改成自动生成。
实现过程
第一版:读取密码文件
最初的版本是这样的——从 password.txt 读取目录名和密码,然后逐个压缩:
@echo off & cd /d "%~dp0"
set "path=%path%;%SystemDrive%\Program Files\7-Zip"
for /f "usebackq tokens=1,*" %%i in ("password.txt") do (
>"%%i.txt" echo,%%j
if exist "%%i\" if not "%%j"=="" (
7z a -tzip -p"%%j" "%%i.zip" "%%i" >nul
echo.完成
)
)缺点很明显:得手动维护 password.txt,每个文件夹都得写一行。
第二版:自动生成随机密码
改成了自动生成密码。这里涉及到批处理中一个关键问题:如何生成随机字符串?
批处理没有现成的随机字符串函数,得用 %RANDOM% 配合字符集手动拼。
set "chars=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%%^^^&*()"
set "len=8"
set "pass="
for /l %%a in (1 1 %len%) do (
set /a "rand=!RANDOM! %% 72"
for %%b in (!rand!) do set "pass=!pass!!chars:~%%b,1!"
)这里面的坑可不少,后面细说。
第三版:加上随机后缀,防止文件名冲突
如果同一个文件夹多次压缩,会覆盖之前的文件。于是给压缩文件名加个6位随机后缀,变成 folder1-Ab3xY9.zip 这样。
密码文件保持和原文件夹同名,方便查找。
最终代码
@echo off
setlocal enabledelayedexpansion
cd /d "%~dp0"
set "path=%path%;%SystemDrive%\Program Files\7-Zip"
rem 配置参数
set "pass_len=8" & rem 密码长度
set "suffix_len=6" & rem 文件名后缀长度
set "pass_chars=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%%^^^&*()"
set "name_chars=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
rem 遍历当前目录下的所有子目录
for /d %%i in (*) do (
if /i not "%%i"=="%~n0" (
rem ====== 生成随机密码 ======
set "pass="
for /l %%a in (1 1 %pass_len%) do (
set /a "rand=!RANDOM! %% 72"
for %%b in (!rand!) do set "pass=!pass!!pass_chars:~%%b,1!"
)
rem ====== 生成压缩包随机后缀 ======
set "suffix="
for /l %%a in (1 1 %suffix_len%) do (
set /a "rand=!RANDOM! %% 62"
for %%b in (!rand!) do set "suffix=!suffix!!name_chars:~%%b,1!"
)
rem ====== 创建密码文件(原始文件夹名) ======
>"%%i.txt" echo 密码:!pass!
rem ====== 创建带随机后缀的压缩包 ======
set "zip_name=%%i-!suffix!"
7z a -tzip -p"!pass!" "!zip_name!.zip" "%%i\" >nul
rem 显示结果
echo [原始文件夹] %%i
echo [压缩文件] !zip_name!.zip
echo [密码文件] %%i.txt
echo [随机密码] !pass!
echo -----------------------
)
)
endlocal踩坑总结
这个脚本看着简单,但里面有几个坑我折腾了很久:
坑一:延迟扩展(enabledelayedexpansion)
在 for 循环里修改变量值,必须开启延迟扩展并用 !var! 引用,不能用 %var%。不然变量值永远不会更新。
setlocal enabledelayedexpansion坑二:特殊字符转义
批处理里 %、^、& 都是特殊字符,要放入字符串必须转义:
| 原字符 | 写法 | 说明 |
|---|---|---|
% | %% | 百分号要双写 |
^ | ^^ | 插入符要双写 |
& | ^& | &符前面加^ |
所以定义密码字符集时写成:
set "pass_chars=...!@#$%%^^^&*()"这行看起来像乱码,但实际存储的值是 !@#$%^&*()。
坑三:变量嵌套引用
从字符集取字符时,!chars:~%%b,1! 需要在 %%b 外面再套一层 for:
for %%b in (!rand!) do set "pass=!pass!!chars:~%%b,1!"这是因为批处理不直接支持在 % 或 ! 扩展中嵌套使用循环变量。
坑四:字符集长度要算准
密码字符集72个字符(26大写+26小写+10数字+10特殊符号),取模要用 %%72。压缩包后缀只用字母数字(62字符),取模用 %%62。不对齐会导致取到空字符,密码变短。
坑五:order 是 MySQL 保留字
这事其实和批处理无关——我一开始想把文章存到博客数据库时用了 order 字段,MySQL 直接报错。后来才发现 order 是保留字,得用反引号括起来或者干脆别用。
使用效果
[原始文件夹] 工作文档
[压缩文件] 工作文档-X7k9mP.zip
[密码文件] 工作文档.txt
[随机密码] aB3@xK9!
-----------------------
[原始文件夹] 图片备份
[压缩文件] 图片备份-fR2wQ6.zip
[密码文件] 图片备份.txt
[随机密码] 7gH$mN2z
-----------------------结语
一个批处理脚本看起来简单,但真正写好还是有不少门道的。特别是延迟扩展和字符转义这两个坑,几乎每个写批处理的人都会踩一遍。
如果你也有批量压缩文件夹的需求,这个脚本可以直接拿去用。记得先装好 7-Zip,放在系统默认路径或者改一下脚本里的路径变量。
最后提醒一句:密码文件建议单独保存好,别和压缩包放一起,不然加密的意义就没了