且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何将文件夹的每个子文件夹中除最新文件外的所有文件压缩为每个子文件夹的一个 ZIP 文件?

更新时间:2023-09-26 11:15:10

此批处理文件可用于此任务:

This batch file can be used for this task:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "FilesToIgnore=1"
set "theYear=%DATE:~-4%"
set "ListFile=%Temp%\%~n0.lst"
del "%ListFile%" 2>nul
for /D %%I in (*) do call :CompressFiles "%%I"
goto EndBatch

:CompressFiles
pushd %1
set "ZipFile=%~nx1%theYear%.zip"
for /F "skip=%FilesToIgnore% eol=| delims=" %%J in ('dir /A-D /B /O-D /TW 2^>nul ^| %SystemRoot%System32findstr.exe /I /L /V /X /C:"%ZipFile%"') do >>"%ListFile%" echo %%J
if exist "%ListFile%" (
    echo Compressing files in directory %1 ...
    7z.exe a -bd -bso0 -i"@%ListFile%" -mx9 -scsDOS -- "%ZipFile%"
    del "%ListFile%"
)
popd
goto :EOF

:EndBatch
endlocal

批处理文件根据动态环境变量 DATE 的区域相关日期字符串动态设置环境变量 theYear.请在命令提示符窗口中执行 echo %DATE:~-4% 并验证输出是否为当前年份,因为 echo %DATE% 输出当前本地日期与最后四个字符是年份.

The batch file sets environment variable theYear dynamically from region dependent date string of dynamic environment variable DATE. Please execute in a command prompt window echo %DATE:~-4% and verify if output is the current year because of echo %DATE% outputs current local date with last four characters being the year.

批处理文件忽略每个目录中的 FilesToIgnore 最新文件.如果 ZIP 文件在先前执行的批处理文件中已经存在,则也将忽略该 ZIP 文件.ZIP 文件永远不会包含在 FilesToIgnore 的数量中,因为 findstr 已经过滤掉了,它过滤了命令 dir 的输出,它输出的文件名没有当前目录中的路径按最后修改时间排序,最新文件先输出,最旧文件最后输出.

The batch file ignores the FilesToIgnore newest files in each directory. Ignored is also the ZIP file if already existing from a previous execution of the batch file. The ZIP file is never included in number of FilesToIgnore because of filtered out already by findstr which filters output of command dir which outputs the file names without path in current directory ordered by last modification time with newest files output first and oldest files output last.

请阅读 7-Zip 的帮助以了解使用的开关和参数.

Please read help of 7-Zip for the used switches and parameters.

要了解使用的命令及其工作原理,请打开命令提示符窗口,在那里执行以下命令,并仔细阅读为每个命令显示的所有帮助页面.

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • del/?
  • dir/?
  • echo/?
  • endlocal/?
  • findstr/?
  • for/?
  • 转到/?
  • if/?
  • popd/?
  • pushd/?
  • set/?
  • setlocal/?

阅读有关 Using Command Redirection Operators2>nul| 的解释.重定向操作符 >| 必须在 FOR 命令行上用脱字符 ^ 转义,才能被解释为Windows 命令解释器在执行命令 FOR 之前处理此命令行时的文字字符,该命令在后台启动的单独命令进程中执行嵌入的命令行.

Read the Microsoft article about Using Command Redirection Operators for an explanation of 2>nul and |. The redirection operators > and | must be escaped with caret character ^ on FOR command line to be interpreted as literal characters when Windows command interpreter processes this command line before executing command FOR which executes the embedded command line in a separate command process started in background.

更新: 7-Zip 版本 19.00.0.0 输出警告并在使用命令行时在每个子目录中创建一个空的 ZIP 文件,如下所述,最初用于批处理文件.我首先认为这是 7-Zip 版本 19.00.0.0 的一个错误,因为这个版本应该也支持 -- 根据其帮助和 7-Zip 16.04.0.0 版适用于使用命令行:

Update: 7-Zip version 19.00.0.0 outputs a warning and creates an empty ZIP file in each subdirectory on using the command line as written below and used initially in batch file. I first thought this is a bug of 7-Zip version 19.00.0.0 because of this version should support also -- according to its help and 7-Zip version 16.04.0.0 works on using the command line:

7z.exe a -bd -bso0 -mx9 -scsDOS -- "%ZipFile%" "@%ListFile%"

必须从此命令行中删除 -- 才能使其与 7-Zip 版本 19.00.0.0 一起使用.

It was necessary to remove -- from this command line to get it working with 7-Zip version 19.00.0.0.

所以我报告了这个问题 7-Zip 的作者很快回复了解释为什么使用 -- 会导致搜索文件名中以 @ 开头的文件,因为 7-Zip 版本 19.00.0.0:

So I reported this issue and the author of 7-Zip quickly replied explaining why the usage of -- results in searching for a file starting with @ in file name since 7-Zip version 19.00.0.0:

我们需要一些方法来从命令行添加 @file-file 名称.
所以 -- 停止 @- 解析,并且 7-Zip 搜索确切名称.
使用 -i@listfile 更安全.

We need some way to add @file and -file names from command line.
So -- stops @ and - parsing, and 7-Zip searches exact names.
It's more safe to use -i@listfile instead.

所以我更新了批处理文件代码并使用选项 -i 指定列表文件,这是指定列表文件的最安全方法.

So I updated the batch file code and specify the list file with option -i which is the most safe method to specify a list file.