批量解压多子文件夹.part分卷压缩包的批处理脚本运行故障排查
分卷压缩包批量解压脚本问题排查
初始目录结构
我在C:\test路径下存放了若干分卷压缩包,目录结构如下:
PARENT folder is C:\test | +--- subfolder1 | +-- file1.part01.rar +-- file1.part02.rar +-- file2.part01.rar +-- file2.part02.rar +..... +--- subfolder2 | +-- file1.part1.rar +-- file1.part2.rar +-- file2.part1.rar +-- file2.part2.rar +......
预期目标
解压完成后实现如下目录结构:
PARENT folder is C:\test | +--- subfolder1 | +-- file1 [folder] +-- file2 [folder] +..... +--- subfolder2 | +-- file1 [folder] +-- file2 [folder] +......
脚本需要实现的完整逻辑:
- 遍历
C:\test下所有子文件夹 - 将每个子文件夹内的分卷压缩包解压到对应子目录,按压缩包名生成单独解压文件夹
- 解压成功后删除原分卷文件
- 将处理完成的子文件夹移动到
done目录
当前编写的批处理脚本无法正常启动运行,原脚本代码如下:
@echo off setlocal EnableExtensions DisableDelayedExpansion for /F "tokens=2 delims=:" %%I in ('%SystemRoot%\System32\chcp.com') do set "CodePage=%%I" %SystemRoot%\System32\chcp.com 65001 2>nul set "PromptForBreak=" if /I "%~1" == "/noprompt" set "PromptForBreak=rem" set "SourceFolder=C:\Test" set "LogExtract=%SourceFolder%\ExtractionLog.txt" set "LogError=%SourceFolder%\ErrorLog.txt" del /Q "%LogExtract%" "%LogError%" 2>nul for /F "eol=| delims=" %%I in ('dir "%SourceFolder%\*" /AD-H /B /ON 2^>nul ^| %SystemRoot%\System32\findstr.exe /I /L /V /X /C:done') do ( set "NoFolderMove=" for /F "eol=| delims=" %%J in ('dir "%SourceFolder%\%%I\*.rar" "%SourceFolder%\%%I\*.zip" /A-D-H /B /ON 2^>nul') do ( if exist "%SourceFolder%\%%I\%%J" ( echo Extracting "%SourceFolder%\%%I\%%J" ... "%ProgramFiles%\WinRAR\WinRAR.exe" x -cfg- -ibck -logpfu="%LogExtract%" -o+ -y -- "%SourceFolder%\%%I\%%J" "%SourceFolder%\%%I\" if errorlevel 1 ( set "NoFolderMove=1" set "ArchiveFile=%SourceFolder%\%%I\%%J" >>"%LogError%" call echo Error %%ErrorLevel%% on extracting "%%ArchiveFile%%" ) else ( echo %%~nJ| %SystemRoot%\System32\findstr.exe /I /R "\.part[0123456789][0123456789]*$" >nul if errorlevel 1 ( del /F "%SourceFolder%\%%I\%%J" ) else for %%# in ("%%~nJ") do del /F /Q "%SourceFolder%\%%I\%%~n#.part*%%~xJ" ) ) ) if not defined NoFolderMove ( md "%SourceFolder%\done" 2>nul if exist "%SourceFolder%\done\" move /Y "%SourceFolder%\%%I" "%SourceFolder%\done\" >nul %PromptForBreak% %SystemRoot%\System32\choice.exe /C NY /N /T 2 /D N /M "Break execution [N/Y]? " %PromptForBreak% if errorlevel 2 goto EndBatch ) ) :EndBatch if defined CodePage %SystemRoot%\System32\chcp.com %CodePage% endlocal
核心问题点
原脚本共有5处缺陷,是导致无法运行、结果不符合预期的直接原因:
- WinRAR路径写死:仅判断64位程序默认安装路径
%ProgramFiles%\WinRAR\WinRAR.exe,32位WinRAR安装在64位系统时路径为%ProgramFiles(x86)%\WinRAR\WinRAR.exe,路径不存在时脚本直接启动失败。 - 未生成独立解压文件夹:解压命令未加自动建目录参数,所有压缩包内容会直接解压到子文件夹根目录,不会生成
file1、file2这类独立文件夹,文件会混杂在一起。 - 分卷包重复解压:遍历所有rar/zip文件时会逐个触发解压,实际上分卷压缩包仅需解压第一个分卷(part01/part1)即可,重复解压会触发覆盖报错、浪费运行时间。
- 分卷匹配逻辑不严谨:原有判断逻辑未兼容不带前导零的分卷命名(如
part1格式),容易出现漏删、误删原压缩文件的问题。 - 移动文件夹无占用等待:解压完成后立即移动文件夹,若WinRAR进程未完全释放文件句柄,会导致移动失败,没有对应等待或报错逻辑。
修正后可用脚本
@echo off setlocal EnableExtensions DisableDelayedExpansion :: 自动适配WinRAR安装路径 set "WinRARPath=" if exist "%ProgramFiles%\WinRAR\WinRAR.exe" set "WinRARPath=%ProgramFiles%\WinRAR\WinRAR.exe" if exist "%ProgramFiles(x86)%\WinRAR\WinRAR.exe" set "WinRARPath=%ProgramFiles(x86)%\WinRAR\WinRAR.exe" if not defined WinRARPath ( echo 未找到WinRAR安装路径,请检查后重试 pause goto EndBatch ) :: 切换代码页为UTF-8避免中文乱码 for /F "tokens=2 delims=:" %%I in ('%SystemRoot%\System32\chcp.com') do set "CodePage=%%I" %SystemRoot%\System32\chcp.com 65001 2>nul set "PromptForBreak=" if /I "%~1" == "/noprompt" set "PromptForBreak=rem" set "SourceFolder=C:\Test" set "LogExtract=%SourceFolder%\ExtractionLog.txt" set "LogError=%SourceFolder%\ErrorLog.txt" del /Q "%LogExtract%" "%LogError%" 2>nul for /F "eol=| delims=" %%I in ('dir "%SourceFolder%\*" /AD-H /B /ON 2^>nul ^| %SystemRoot%\System32\findstr.exe /I /L /V /X /C:done') do ( set "NoFolderMove=" for /F "eol=| delims=" %%J in ('dir "%SourceFolder%\%%I\*.rar" "%SourceFolder%\%%I\*.zip" /A-D-H /B /ON 2^>nul') do ( set "SkipExtract=0" :: 判断是否为非首个分卷,是则直接跳过解压 echo %%~nJ| %SystemRoot%\System32\findstr.exe /I /R "\.part[0123456789][0123456789]*$" >nul if not errorlevel 1 ( for /F "tokens=2 delims=." %%b in ("%%~nJ") do ( if /I not "%%b" == "part1" if /I not "%%b" == "part01" set "SkipExtract=1" ) ) if %SkipExtract% == 0 if exist "%SourceFolder%\%%I\%%J" ( echo Extracting "%SourceFolder%\%%I\%%J" ... :: 加-ad参数自动按压缩包名生成独立解压目录 "%WinRARPath%" x -ad -cfg- -ibck -logpfu="%LogExtract%" -o+ -y -- "%SourceFolder%\%%I\%%J" "%SourceFolder%\%%I\" if errorlevel 1 ( set "NoFolderMove=1" set "ArchiveFile=%SourceFolder%\%%I\%%J" >>"%LogError%" call echo Error %%ErrorLevel%% on extracting "%%ArchiveFile%%" ) else ( echo %%~nJ| %SystemRoot%\System32\findstr.exe /I /R "\.part[0123456789][0123456789]*$" >nul if errorlevel 1 ( del /F "%SourceFolder%\%%I\%%J" ) else ( for %%# in ("%%~nJ") do del /F /Q "%SourceFolder%\%%I\%%~n#.part*%%~xJ" ) ) ) ) if not defined NoFolderMove ( md "%SourceFolder%\done" 2>nul :: 等待1秒释放文件占用再执行移动 timeout /t 1 /nobreak >nul if exist "%SourceFolder%\done\" move /Y "%SourceFolder%\%%I" "%SourceFolder%\done\" >nul %PromptForBreak% %SystemRoot%\System32\choice.exe /C NY /N /T 2 /D N /M "Break execution [N/Y]? " %PromptForBreak% if errorlevel 2 goto EndBatch ) ) :EndBatch if defined CodePage %SystemRoot%\System32\chcp.com %CodePage% endlocal
使用说明:如果不需要运行中途的暂停确认提示,执行脚本时加
/noprompt参数即可。
内容的提问来源于stack exchange,提问作者Jack Rock
相关产品推荐
相关产品推荐

