用批处理实现文件夹批量加密压缩,自动生成随机密码

前言

最近有个需求:手头有一堆文件夹需要逐个加密压缩,每个还要用不同的密码。手动一个一个来太折磨人了,于是想写个批处理一键搞定。

折腾过程中踩了不少坑,特别是批处理里那些转义字符和延迟扩展的坑,今天把最终方案分享出来。

需求分析

我需要这样一个小工具:

  • 遍历当前目录下的所有子文件夹
  • 每个文件夹自动生成一个随机密码
  • 用该密码加密压缩成 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,放在系统默认路径或者改一下脚本里的路径变量。

最后提醒一句:密码文件建议单独保存好,别和压缩包放一起,不然加密的意义就没了

Last modification:May 21st, 2026 at 12:03 am
如果觉得我的文章对你有用,请随意赞赏