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

标签 batch-file command-line command zip 7zip

我正在尝试创建一个批处理脚本,该脚本将压缩每个子目录中除最新(或最新的几个)之外的所有内容。我目前正在 Windows 中尝试使用 7-Zip,但从技术上讲,该目录位于 Linux 服务器上,因此欢迎任何针对 Linux 命令的建议。

目录结构是这样的:

Directory-Parent
 ---Sub-Directory-1
 --------File1
 --------File2
 --------File3
 ---Sub-Directory-2
 --------File1
 --------File2

我想在Directory-Parent级别运行一个批处理,该批处理将在除最新文件(或少数文件,如果可能)之外的所有文件的每个子目录中创建一个zip。我还想将年份添加到 zip 文件名的末尾。

所以结果是:

Directory-Parent
 -Sub-Directory-1
 --------File1
 --------Sub-Directory-12019.zip
 ---Sub-Directory-2
 --------File1
 --------Sub-Directory-22019.zip

我尝试了嵌套的 for 循环,但似乎无法得到它。我已在集合 (IN) 中尝试使用带有skip和dirfor命令,但无法让它工作。

我目前有以下脚本。

SET theYear=2019
For /D %%d in (*.*) do 7z a "%%d\%%d%theYear%.zip" ".\%%d\*"

这一切都完成了,只是我不知道如何排除每个文件夹中的最新文件(根据上次修改时间的最新文件)。

最佳答案

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

@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%\System32\findstr.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% 输出当前本地日期的最后四位字符为年份。

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

使用的开关和参数请阅读7-Zip的帮助。

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

  • 删除/?
  • 目录/?
  • 回显/?
  • endlocal/?
  • findstr/?
  • 对于/?
  • 转到/?
  • 如果/?
  • popd/?
  • pushd/?
  • 设置/?
  • setlocal/?

阅读有关 Using Command Redirection Operators 的 Microsoft 文章了解 2>nul| 的解释。重定向运算符 >| 必须在 FOR 命令行上使用脱字符号 ^ 进行转义才能解释为文字Windows 命令解释器在执行命令 FOR 之前处理此命令行时的字符,该命令使用在后台启动的单独命令进程来执行嵌入式命令行。

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

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

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

所以我reported this issue 7-Zip 的作者很快回复解释了为什么使用 -- 会导致搜索文件名以 @ 开头的文件,因为 7-Zip 版本 19.00.0.0:

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 指定列表文件,这是指定列表文件的最安全方法。

关于batch-file - 如何将文件夹的每个子文件夹中除最新文件之外的所有文件压缩为每个子文件夹一个 ZIP 文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57613888/

相关文章:

bash - bash 中的 matlab 批处理并行化

java - 有没有办法在 R Studio 中运行 Mac 命令行操作?

windows - 对于批处理中的命令

batch-file - 为什么批解释评论?

if-statement - DOS 批处理文件中可以有 IF block 吗?

node.js - 使用批处理文件一次运行多个NodeJS项目

java - 无法执行二进制文件: Exec format error

linux - shell cmd transfair windows cmd

linux - 关于 su 命令的查询

linux - shell 中的 sed 命令不会替换模式的第二个匹配项