标题: [文件操作] 求助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
- @echo off
- rem 保存为ansi
- rem 代码使用winrar\下的rar.exe,使用需添加到系统环境变量,或者写明绝对路径
- cd /d "%~dp0"
- set pwd=QWEasd
- set f1=D:\实例_20240731_151654\A
- set f2=D:\实例_20240731_151654\C
- set log=d:\1.txt
-
- md "%f2%" 2>nul
- pushd "%f1%"
- call :getdt d
- (for /d %%d in (*) do (
- pushd "%%d"
- for /f "delims=" %%a in ('forfiles /s /m * /c "cmd /c if @isdir equ FALSE echo @relpath"') do (
- call :getdt
- set /p="%%~dpa,%%~nxa,"<nul
- rar a "%f2%\%%d.zip" -p%d%%pwd% "%%~a" 1>nul 2>nul
- if errorlevel 1 (
- echo 压缩失败
- ) else (
- echo 压缩成功
- )
- )
- popd
- ))>>"%log%"
- pause
- exit
-
- :getdt
- for /f %%a in ('wmic os get localdatetime ^|findstr [0-9]') do (
- set t=%%a
- )
- if "%~1" equ "d" (
- set %~1=%t:~0,4%%t:~4,2%%t:~6,2%
- ) else (
- set /p="%t:~0,4%年%t:~4,2%月%t:~6,2%日%t:~8,2%时%t:~10,2%分%t:~12,2%秒,"<nul
- )
- exit /b
复制代码
作者: ppll2030 时间: 2024-7-31 21:24
- @echo off
- set "input=D:\我的文档\桌面\批量压缩文件\实例\A"
- set "output=D:\我的文档\桌面\批量压缩文件\实例\B"
- rem 采用7zip压缩,请修改为实际路径
- set "exe=D:\实际路径\7-Zip\7z.exe"
- set "pwd=20240731QWEasd"
- pushd %input%
- (for /d %%d in (*) do (
- "%exe%" a -p%pwd% -t7z "%output%\%%d.7z" ".\%%d\*" >nul 2>nul
- if errorlevel 1 (
- echo %DATE% %TIME% %%~fd --- 压缩失败
- ) else (
- echo %DATE% %TIME% %%~fd --- 压缩成功
- )
-
- ))>%~dp0LOG.txt
- popd
- start "" LOG.txt
- exit/b
复制代码
作者: aloha20200628 时间: 2024-8-1 17:59
在任何一个复合语块(如for或if)中的 %var% 变量均会被预先赋值,errorlevel亦是%var%
例如下式中的 errorlevel 会被预赋值为零,而无视循环体内每次 rar.exe 的真实返回值
假定下式中的 abc.zip, 123.rar 均为不存在的压缩包文件...
- @echo off &for %%F in ("abc.zip" "123.rar") do (
- rar.exe x %%F 2>nul >nul
- if errorlevel 0 (echo,解压成功) else echo,解压失败
- )
- 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楼代码中:- if errorlevel 0 (echo,解压成功) else echo,解压失败
复制代码
和直接复制代码
效果是一样的。
代码这样写是可以的:- if not errorlevel 1 (echo,解压成功) else echo,解压失败
复制代码
作者: 77七 时间: 2024-8-2 09:03
站长前几天刚讲过(跳转),不过errorlevel可为负值,代码设定上应该还是没问题。- @echo off
- call :1 -1
- if errorlevel 0 (
- echo a
- ) else (
- echo b
- )
- pause
- exit
- :1
- 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
- FIND.EXE
- (a) Target string found (=f0und) = ERRORLEVEL 0
- (b) Target string missing (=m1ssing) = ERRORLEVEL 1
- (c) find /? = ERRORLEVEL 1
- (d) Parameter format not correct = ERRORLEVEL 2
- (e) Specified file to search not found = ERRORLEVEL 2
- (f) Specified file in use + Fail reply = ERRORLEVEL 2
- (g) Drive not ready + Fail reply = ERRORLEVEL 2
- (h) Specified file in use + Abort reply = ERRORLEVEL 5
- (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- @echo off &for %%s in ("$$$.txt" "###.txt") do (
- echo,%%s|find "#" 2>nul >nul
- if errorlevel 1 (echo,"errorlevel = 1") else (echo,"errorlevel = 0")
- )
- 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%,如- @echo off &setlocal enabledelayedexpansion
- for %%s in ("$$$.txt" "###.txt") do (
- echo,%%s|find "#" 2>nul >nul
- if !errorlevel! neq 0 (echo,"errorlevel /= 0") else (echo,"errorlevel = 0")
- )
- pause&exit/b
复制代码
五。关于 errorlevel 的不等式判断用法,存在一个捷径,即直接采用 || 和 && 逻辑运算符, 如- @echo off &for %%s in ("$$$.txt" "###.txt") do (
- echo,%%s|find "#" 2>nul >nul||(echo,"errorlevel 》失败")&&(echo,"errorlevel 》成功")
- )
- 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好像只是个空值。
- @echo off
- setlocal enabledelayedexpansion
- 123 2>nul
- call :1
- set /a "var=errorlevel" &echo %errorlevel%
- echo %var%
- endlocal
- echo=
-
-
- setlocal enabledelayedexpansion
- 123 2>nul
- set /a "var=errorlevel" &echo %errorlevel%
- echo %var%
- endlocal
- pause
-
- :1
- 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获取进程环境变量。- @echo off
- set __cd__
- echo,内置变量__cd__=%__cd__%
- echo,设置环境变量&set "__cd__=999"
- set __cd__
- echo,变量__cd__=%__cd__%
- echo,
- set /a var=__cd__
- set __cd__
- echo,%var%
- 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 |