Board logo

标题: [文件操作] 求助BAT脚本批量压缩文件 [打印本页]

作者: 304802301    时间: 2024-7-31 15:18     标题: 求助BAT脚本批量压缩文件

1、某个路径A下有若干个文件夹,比如
D:\我的文档\桌面\批量压缩文件\实例\A\54434aaaa\1.txt
D:\我的文档\桌面\批量压缩文件\实例\A\76768sdsfe\2.txt
D:\我的文档\桌面\批量压缩文件\实例\A\eaa202121212\3.txt


2、需要bat执行自动压缩,并保存到另一个路径B下,压缩结果如下:
D:\我的文档\桌面\批量压缩文件\实例\B\54434aaaa.zip
D:\我的文档\桌面\批量压缩文件\实例\B\76768sdsfe.zip
D:\我的文档\桌面\批量压缩文件\实例\B\eaa202121212.zip

3、压缩过程中需要添加密码,密码是年月日+指定字符,比如密码是20240731QWEasd
4、压缩过程中把压缩结果输出到指定路径的日志文件里,包含时间、文件名字、源文件的完整路径、压缩结果

示例:链接: https://pan.baidu.com/s/1nZLGJmikGi-udcdweDsY9w 提取码: p4qi
请大佬帮忙写个bat,万分感谢!
作者: 77七    时间: 2024-7-31 16:32

上传3个文件夹和3个压缩包没什么意义...
日志文件相比来说更需要说明,请给个示例
作者: 304802301    时间: 2024-7-31 16:36

回复 2# 77七

压缩过程中把压缩结果输出到指定路径的日志文件里,包含时间、文件名字、源文件的完整路径、压缩结果
XXXX年XX月XX日XX点XX分XX秒,XX路径,XX文件名,压缩成功
XXXX年XX月XX日XX点XX分XX秒,XX路径,XX文件名,压缩失败


就类似这种的日志格式,大致上差不多就行
作者: 304802301    时间: 2024-7-31 16:45

回复 2# 77七


    再补充下,只要A路径下的子文件夹,每个子文件夹及下面的文件+文件夹都打包成一个压缩包即可(不考虑再下一层子还是否有子文件夹的情况)。
作者: 77七    时间: 2024-7-31 18:54

回复 4# 304802301


  
  1. @echo off
  2. rem 保存为ansi
  3. rem 代码使用winrar\下的rar.exe,使用需添加到系统环境变量,或者写明绝对路径
  4. cd /d "%~dp0"
  5. set pwd=QWEasd
  6. set f1=D:\实例_20240731_151654\A
  7. set f2=D:\实例_20240731_151654\C
  8. set log=d:\1.txt
  9. md "%f2%" 2>nul
  10. pushd "%f1%"
  11. call :getdt d
  12. (for /d %%d in (*) do (
  13. pushd "%%d"
  14. for /f "delims=" %%a in ('forfiles /s /m * /c "cmd /c if @isdir equ FALSE echo @relpath"') do (
  15. call :getdt
  16. set /p="%%~dpa,%%~nxa,"<nul
  17. rar a "%f2%\%%d.zip" -p%d%%pwd% "%%~a" 1>nul 2>nul
  18. if errorlevel 1 (
  19. echo 压缩失败
  20. ) else (
  21. echo 压缩成功
  22. )
  23. )
  24. popd
  25. ))>>"%log%"
  26. pause
  27. exit
  28. :getdt
  29. for /f %%a in ('wmic os get localdatetime ^|findstr [0-9]') do (
  30. set t=%%a
  31. )
  32. if "%~1" equ "d" (
  33. set %~1=%t:~0,4%%t:~4,2%%t:~6,2%
  34. ) else (
  35. set /p="%t:~0,4%年%t:~4,2%月%t:~6,2%日%t:~8,2%时%t:~10,2%分%t:~12,2%秒,"<nul
  36. )
  37. exit /b
复制代码

作者: ppll2030    时间: 2024-7-31 21:24

  1. @echo off
  2. set "input=D:\我的文档\桌面\批量压缩文件\实例\A"
  3. set "output=D:\我的文档\桌面\批量压缩文件\实例\B"
  4. rem 采用7zip压缩,请修改为实际路径
  5. set "exe=D:\实际路径\7-Zip\7z.exe"
  6. set "pwd=20240731QWEasd"
  7. pushd %input%
  8. (for /d %%d in (*) do (
  9. "%exe%" a -p%pwd% -t7z "%output%\%%d.7z" ".\%%d\*" >nul 2>nul
  10. if errorlevel 1 (
  11. echo %DATE% %TIME% %%~fd --- 压缩失败
  12. ) else (
  13. echo %DATE% %TIME% %%~fd --- 压缩成功
  14. )
  15. ))>%~dp0LOG.txt
  16. popd
  17. start "" LOG.txt
  18. exit/b
复制代码

作者: aloha20200628    时间: 2024-8-1 17:59


在任何一个复合语块(如for或if)中的 %var% 变量均会被预先赋值,errorlevel亦是%var%
例如下式中的 errorlevel 会被预赋值为零,而无视循环体内每次 rar.exe 的真实返回值
假定下式中的 abc.zip, 123.rar 均为不存在的压缩包文件...
  1. @echo off &for %%F in ("abc.zip" "123.rar") do (
  2. rar.exe x %%F 2>nul >nul
  3. if errorlevel 0 (echo,解压成功) else echo,解压失败
  4. )
  5. pause&exit/b
复制代码

作者: buyiyang    时间: 2024-8-1 18:36

回复 7# aloha20200628

if errorlevel 0 如何证明 errorlevel 会被预赋值为零
作者: aloha20200628    时间: 2024-8-1 19:30

回复 8# buyiyang

试试7楼的代码运行结果,应该总是显示‘成功’,除非在for之前errorlevel已被赋予非零值...

作者: buyiyang    时间: 2024-8-1 20:03

回复 9# aloha20200628

http://www.bathome.net/redirect. ... 9133&pid=282222
作者: qixiaobin0715    时间: 2024-8-2 08:33

本帖最后由 qixiaobin0715 于 2024-8-2 08:52 编辑

无论是在“复合语块”中还是在外部其它任何位置,判断语句“if errorlevel 0 ...”在任何时候都成立。换句话说,用不用都一样,无任何意义。
7楼代码中:
  1. if errorlevel 0 (echo,解压成功) else echo,解压失败
复制代码
和直接
  1. echo,解压成功
复制代码
效果是一样的。
代码这样写是可以的:
  1. if not errorlevel 1 (echo,解压成功) else echo,解压失败
复制代码

作者: 77七    时间: 2024-8-2 09:03

站长前几天刚讲过(跳转),不过errorlevel可为负值,代码设定上应该还是没问题。
  1. @echo off
  2. call :1 -1
  3. if errorlevel 0 (
  4. echo a
  5. ) else (
  6. echo b
  7. )
  8. pause
  9. exit
  10. :1
  11. exit /b %~1
复制代码

作者: aloha20200628    时间: 2024-8-2 10:31

本帖最后由 aloha20200628 于 2024-8-2 10:38 编辑


这个 errorlevel 还真是有趣...
但用过7楼代码的试者可知》无论 rar.exe 在循环体内的每次真实返回值如何,echo显示均为'成功',因此用此法判断 rar.exe ‘解压失败’ 是无效的。
     不知 5-6楼 认可这个推论吗?

作者: qixiaobin0715    时间: 2024-8-2 10:37

本帖最后由 qixiaobin0715 于 2024-8-2 10:39 编辑

回复 12# 77七
不是太懂,记得以前看过%errorlevel%取值范围是0~255,你这里的代码是强制定义了环境变量?-1换成10000%errorlevel%的值就是10000,不知道实际应用上有何作用。
作者: qixiaobin0715    时间: 2024-8-2 10:43

本帖最后由 qixiaobin0715 于 2024-8-2 10:55 编辑

判断语句 if errorlevel 0 ... 的意思是,如果errorlevel的返回值是大于或等于0,要执行什么命令。
可以在cmd窗口写入:if /? 查询
作者: 77七    时间: 2024-8-2 12:17

回复 14# qixiaobin0715


比如 批处理各命令错误返回值errorlevel一览 问中提到find.exe
  1. FIND.EXE
  2. (a) Target string found (=f0und)                 = ERRORLEVEL 0
  3. (b) Target string missing (=m1ssing)             = ERRORLEVEL 1
  4. (c) find /?                                     = ERRORLEVEL 1
  5. (d) Parameter format not correct                = ERRORLEVEL 2
  6. (e) Specified file to search not found          = ERRORLEVEL 2
  7. (f) Specified file in use + Fail reply          = ERRORLEVEL 2
  8. (g) Drive not ready + Fail reply                = ERRORLEVEL 2
  9. (h) Specified file in use + Abort reply          = ERRORLEVEL 5
  10. (i) Drive not ready + Abort reply                = ERRORLEVEL 5
复制代码


多条退出码相同,如果能通过代码判断细分这些结果,自定义一个退出码,得到的反馈更具体。如第三方工具的退出码,同样也是作者自定义的。(文章比较古老,仅举个例子)
作者: 77七    时间: 2024-8-2 12:27

回复 13# aloha20200628


   大佬的方法和5、6楼的不是一样的...
if errorlevel 0 当errorlevel 值大于等于0都是成立的,即 errorlevel值为1也是成立。
if errorlevel 1 排除了 errorlevel值为0的情况,所以当 if errorlevel 1 成立,说明上一条命令执行失败了。
作者: aloha20200628    时间: 2024-8-2 16:41


为探究 ‘在批处脚本中如何可靠使用 errorlevel 判断系统内置或第三方应用的运行结果返回码’,查看了有关人气较高的老帖,其中列出三篇供有兴趣者参考
2008年老帖》https://devblogs.microsoft.com/oldnewthing/20080926-00/?p=20743
2013年老帖》http://steve-jansen.github.io/gu ... 3-return-codes.html
2012年老帖》https://stackoverflow.com/questi ... -windows-batch-file
至此总算有了一个要点小结(仅供参考):
一。订正7楼的说法,errorlevel 其实是系统维护的一个内置变量,用于捕获系统或第三方应用程序的运行结果返回码,与可在批处脚本中自定义的%errorlevel%不是一回事,并与是否在复合语块内使用无关。
二。if errorlevel n 用于判断系统或第三方应用程序的运行结果返回码,应该从非零值起验,如已知 find.exe 的成功/失败返回码=0/1
  1. @echo off &for %%s in ("$$$.txt" "###.txt") do (
  2. echo,%%s|find "#" 2>nul >nul
  3. if errorlevel 1 (echo,"errorlevel = 1") else (echo,"errorlevel = 0")
  4. )
  5. pause&exit/b
复制代码
三。若系统或第三方应用程序的运行结果返回码不止0/1,if errorlevel n 判断式则应从较高值起验,如
      if errorlevel 9 goto ...
      if errorlevel 8 goto ...
四。由于 if errorlevel n 判断式中的 n 是等式判断,故可采用自定义变量 %errorlevel% 自动接收 errorlevel 即时传值并实现不等式判断,但前提是%errorlevel% 未被预先赋值,因此在复合语块中采用此法,就要启用延迟变量 !errorlevel! 而非 %errorlevel%,如
  1. @echo off &setlocal enabledelayedexpansion
  2. for %%s in ("$$$.txt" "###.txt") do (
  3. echo,%%s|find "#" 2>nul >nul
  4. if !errorlevel! neq 0 (echo,"errorlevel /= 0") else (echo,"errorlevel = 0")
  5. )
  6. pause&exit/b
复制代码
五。关于 errorlevel 的不等式判断用法,存在一个捷径,即直接采用 || 和 && 逻辑运算符, 如
  1. @echo off &for %%s in ("$$$.txt" "###.txt") do (
  2. echo,%%s|find "#" 2>nul >nul||(echo,"errorlevel 》失败")&&(echo,"errorlevel 》成功")
  3. )
  4. pause&exit/b
复制代码

作者: 77七    时间: 2024-8-2 22:35

个人觉得 系统命令、第三方工具、用户自定义 中的 %errorlevel% 仅仅是定义方不一样。
if errorlevel 是特定用法,只判断 大于等于,且自带变量延迟扩展属性,如同set /a ,方便了在复合语句内判断errorlevel值。
作者: buyiyang    时间: 2024-8-3 09:40

回复 19# 77七


进程环境变量和脚本内置变量是不一样的,使用set只能定义进程环境变量。
cmd脚本内置变量就有errorlevel,以上个命令的LastRetCode为值。
使用%errorlevel%或!errorlevel!扩展变量首先通过GetEnvironmentStrings获取进程环境变量,如果不存在再获取脚本内置变量。
值得注意的是set /a var=errorleve只会获取进程环境变量。
使用if errorlevel时既不会获取进程环境变量也不会获取脚本内置变量,它直接将后面的数字与LastRetCode进行比较,errorlevel只是if的一个命令参数不是变量名。
作者: 77七    时间: 2024-8-3 10:53

本帖最后由 77七 于 2024-8-3 11:12 编辑

回复 20# buyiyang


   谢谢大佬指点!我的理解错误。
大佬,set /a var=errorlevel,我测试了一下,这里的errorlevel好像只是个空值。
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. 123 2>nul
  4. call :1
  5. set /a "var=errorlevel" &echo %errorlevel%
  6. echo %var%
  7. endlocal
  8. echo=
  9. setlocal enabledelayedexpansion
  10. 123 2>nul
  11. set /a "var=errorlevel" &echo %errorlevel%
  12. echo %var%
  13. endlocal
  14. pause
  15. :1
  16. exit /b -1
复制代码

作者: buyiyang    时间: 2024-8-3 13:31

回复 21# 77七


    这正是我所说的“set /a var=errorleve只会获取进程环境变量”。
然后因为进程环境变量中没有errorlevel变量,所以在算数表达式中就是0。进程环境变量可以通过set查看。

内置变量在启用命令扩展后才能使用,批处理脚本是默认启用的。
不过有一个例外,__cd__变量无论是否启用命令扩展都能使用,并且%或!引用该变量时只会获取内置变量的值;
但使用set /a var=__cd__或set __cd__仍然只会通过GetEnvironmentStrings获取进程环境变量。
  1. @echo off
  2. set __cd__
  3. echo,内置变量__cd__=%__cd__%
  4. echo,设置环境变量&set "__cd__=999"
  5. set __cd__
  6. echo,变量__cd__=%__cd__%
  7. echo,
  8. set /a var=__cd__
  9. set __cd__
  10. echo,%var%
  11. pause&exit
复制代码
关于__cd__变量可以参考https://stackoverflow.com/questions/20156490/why-cant-i-access-a-variable-named-cd-on-windows-7/20169219#20169219
作者: 77七    时间: 2024-8-3 21:05

回复 22# buyiyang


   
谢谢大佬指点!

第一次知道有__cd__ 这个变量,还可以这样用,长知识了。
作者: h2bx86    时间: 2024-8-4 09:59

if errorlevel 0 (echo,解压成功) else echo,解压失败

应该写成

if %errorlevel%==0 (echo,解压成功) else echo 解压失败




欢迎光临 批处理之家 (http://bathome.net./) Powered by Discuz! 7.2