Windows 批量解压 TAR 文件脚本:支持文件数量校验、断点续解压和自动跳过

Windows 批量解压 TAR 文件脚本:支持文件数量校验、断点续解压和自动跳过 文章目录一、需求说明二、脚本功能三、为什么使用 7-Zip1. 7-Zip 支持命令行调用2. 方便读取 tar 包内部文件列表3. 支持跳过已存在文件适合断点续解压4. 对 tar 文件支持比较稳定5. 适合处理大量小文件场景四、完整 BAT 脚本五、使用前需要修改的地方六、脚本运行逻辑说明1. 检查 7-Zip 是否存在2. 检查源目录是否存在3. 检查目标盘符是否可访问4. 统计 tar 文件总数5. 每个 tar 文件解压到同名目录七、文件数量校验逻辑1. 统计 tar 包内部文件数量2. 统计目标目录已有文件数量3. 判断是否需要解压八、关于“重新解压”的理解九、完成标记文件的作用十、运行效果示例十一、需要注意的问题1. 这个脚本适合 tar 包不适合所有压缩格式2. 文件数量校验不是百分百严格校验3. 大量小文件会非常慢4. 目标磁盘状态很重要十二、适用场景十三、总结一、需求说明我的目标是将指定文件夹中的所有.tar文件批量解压到另一个指定目录中。例如源目录 C:\Users\1\Desktop\1 目标目录 D:\disk8假设源目录中有disk8_backup.tar data_001.tar data_002.tar那么脚本会自动解压为D:\disk8\disk8_backup\ D:\disk8\data_001\ D:\disk8\data_002\也就是说每个.tar文件都会解压到一个与压缩包同名的文件夹中。二、脚本功能这个脚本主要实现了以下功能批量查找源目录中的所有.tar文件每个 tar 文件解压到独立的同名文件夹解压前检查 7-Zip 是否存在检查源目录、目标盘符、目标目录是否可用统计 tar 包内部文件数量统计目标目录中已经存在的文件数量如果目标文件数量已经满足要求则跳过解压如果已经存在完成标记_extract_done.flag则直接跳过如果目标目录文件数量不足则继续解压解压成功后写入完成标记最后输出成功、失败、跳过、重新解压的统计结果。三、为什么使用 7-Zip这里之所以选择使用 7-Zip而不是直接使用 Windows 自带的解压方式主要有几个原因。1. 7-Zip 支持命令行调用这个脚本需要通过.bat批处理自动执行解压任务因此需要一个可以在命令行中调用的解压工具。7-Zip 安装后会提供7z.exe可以直接在 BAT 脚本中使用例如C:\Program Files\7-Zip\7z.exe x xxx.tar -o目标目录这样就可以实现自动化批量解压而不需要手动右键解压每一个文件。2. 方便读取 tar 包内部文件列表脚本中不仅要解压 tar 文件还需要先统计 tar 包内部有多少个文件。7-Zip 可以通过下面的命令列出压缩包内部内容%SEVENZIP_PATH% l -slt xxx.tar其中l表示列出压缩包内容-slt表示以更详细、更适合脚本解析的方式输出文件信息。脚本正是利用这个功能统计 tar 包内部的文件数量再和目标目录中已经解压出来的文件数量进行对比。3. 支持跳过已存在文件适合断点续解压脚本中实际使用的解压命令是%SEVENZIP_PATH% x %%i -aos -o!OUT!其中-aos的作用是Skip extracting of existing files也就是跳过已经存在的文件。这对我的场景非常重要。因为我的数据里有大量几 KB 的小文件如果解压中途失败或被迫中断下次重新运行脚本时不希望已经解压过的文件再被覆盖一遍。使用-aos后脚本可以在已有文件的基础上继续解压缺失文件效果上类似“断点续解压”。4. 对 tar 文件支持比较稳定.tar本质上是一种归档格式经常用于打包大量文件。在 Windows 环境下直接处理.tar文件有时不如 7-Zip 直观。7-Zip 对.tar、.zip、.7z等常见压缩或归档格式支持较好命令行参数也比较清晰因此比较适合写进批处理脚本中。5. 适合处理大量小文件场景我这次整理的数据不是几个大文件而是非常多几 KB 的.txt小文件。在这种情况下手动解压和手动检查都非常不现实。使用 7-Zip 配合 BAT 脚本可以做到批量处理多个 tar 包自动创建输出目录自动统计 tar 内部文件数量自动判断是否需要继续解压自动跳过已存在文件解压完成后写入标记文件。四、完整 BAT 脚本下面是完整脚本可以保存为unzip_tar.bat然后双击运行或者在 CMD 中运行。echo off setlocal enabledelayedexpansion chcp 936 nul mode con: cols120 lines30 color 07 :: :: 固定路径 :: set SEVENZIP_PATHC:\Program Files\7-Zip\7z.exe set SRC_DIRC:\Users\1\Desktop\1 set DEST_DIRD:\disk8 :: set TAR_LIST_FILE%SRC_DIR%\_tar_list_temp.txt set DEST_DRIVE%DEST_DIR:~0,3% echo. echo echo 批量解压TAR文件 - 文件数量校验版 echo echo 源目录 : %SRC_DIR% echo 目标根目录 : %DEST_DIR% echo 目标盘符 : %DEST_DRIVE% echo echo. if not exist %SEVENZIP_PATH% ( echo 错误未找到7-Zip请检查路径 echo %SEVENZIP_PATH% pause exit /b ) if not exist %SRC_DIR% ( echo 错误源目录不存在 echo %SRC_DIR% pause exit /b ) if not exist %DEST_DRIVE% ( echo 错误目标盘符不存在或不可访问 echo %DEST_DRIVE% echo. echo 请先在CMD中测试 echo dir %DEST_DRIVE% echo. echo 如果该盘符不存在请把 DEST_DIR 改成真实存在的路径。 pause exit /b ) if not exist %DEST_DIR% ( mkdir %DEST_DIR% if errorlevel 1 ( echo 错误无法创建目标目录 echo %DEST_DIR% echo 请检查权限或尝试以管理员身份运行。 pause exit /b ) ) if exist %TAR_LIST_FILE% del %TAR_LIST_FILE% nul 21 :: 统计tar文件总数 set TOTAL0 for %%f in (%SRC_DIR%\*.tar) do ( if exist %%f set /a TOTAL1 ) if %TOTAL% equ 0 ( echo 未找到任何tar文件 pause exit /b ) echo 找到tar文件总数%TOTAL% echo 开始检查并解压处理... echo. set CUR0 set SUCCESS0 set FAILED0 set SKIPPED0 set REEXTRACT0 for %%i in (%SRC_DIR%\*.tar) do ( if exist %%i ( set /a CUR1 set /a PERCENTCUR*100/TOTAL set FILE%%~nxi set OUT%DEST_DIR%\%%~ni set DONE_FLAG!OUT!\_extract_done.flag set TAR_FILE_COUNT0 set OUT_FILE_COUNT0 set OUT_FILE_COUNT_AFTER0 set NEED_EXTRACT1 echo echo 已处理 !CUR!/%TOTAL% 进度 !PERCENT!%% echo 正在检查!FILE! echo 解压目录!OUT! echo if exist %TAR_LIST_FILE% del %TAR_LIST_FILE% nul 21 %SEVENZIP_PATH% l -slt %%i %TAR_LIST_FILE% 2nul if not exist %TAR_LIST_FILE% ( echo 状态无法读取tar文件列表 set /a FAILED1 ) else ( for /f %%a in (findstr /c:Folder - %TAR_LIST_FILE% ^| find /c /v ) do ( set TAR_FILE_COUNT%%a ) if exist !OUT!\ ( for /f %%a in (dir /a-d /b /s !OUT! 2^nul ^| find /c /v ) do ( set OUT_FILE_COUNT%%a ) ) else ( set OUT_FILE_COUNT0 ) echo tar内部文件数!TAR_FILE_COUNT! echo 目标目录文件数!OUT_FILE_COUNT! if exist !DONE_FLAG! ( echo 状态已检测到完成标记跳过 set NEED_EXTRACT0 set /a SKIPPED1 ) else ( if !TAR_FILE_COUNT! gtr 0 ( if !OUT_FILE_COUNT! geq !TAR_FILE_COUNT! ( echo 状态目标目录文件数量已满足判断为已解压跳过并补写标记 if not exist !OUT! mkdir !OUT! nul 21 echo 完成时间%date% %time% !DONE_FLAG! echo 源文件%%i !DONE_FLAG! echo 解压目录!OUT! !DONE_FLAG! echo tar内部文件数!TAR_FILE_COUNT! !DONE_FLAG! echo 目标目录文件数!OUT_FILE_COUNT! !DONE_FLAG! echo 标记来源根据文件数量校验自动补写 !DONE_FLAG! set NEED_EXTRACT0 set /a SKIPPED1 ) ) ) if !NEED_EXTRACT!1 ( if !OUT_FILE_COUNT! gtr 0 ( echo 状态目标目录文件数量不足重新解压 set /a REEXTRACT1 ) else ( echo 状态目标目录为空或不存在开始解压 ) if not exist !OUT! ( mkdir !OUT! nul 21 if errorlevel 1 ( echo 状态无法创建解压目录可能权限不足 set /a FAILED1 ) ) if exist !OUT!\ ( %SEVENZIP_PATH% x %%i -aos -o!OUT! nul 21 if !errorlevel! equ 0 ( for /f %%a in (dir /a-d /b /s !OUT! 2^nul ^| find /c /v ) do ( set OUT_FILE_COUNT_AFTER%%a ) echo 解压后文件数!OUT_FILE_COUNT_AFTER! if !OUT_FILE_COUNT_AFTER! geq !TAR_FILE_COUNT! ( echo 完成时间%date% %time% !DONE_FLAG! echo 源文件%%i !DONE_FLAG! echo 解压目录!OUT! !DONE_FLAG! echo tar内部文件数!TAR_FILE_COUNT! !DONE_FLAG! echo 解压后文件数!OUT_FILE_COUNT_AFTER! !DONE_FLAG! echo 标记来源本次解压成功并通过文件数量校验 !DONE_FLAG! echo 状态解压成功文件数量校验通过 set /a SUCCESS1 ) else ( echo 状态解压完成但文件数量不足可能解压不完整 set /a FAILED1 ) ) else ( echo 状态解压失败 set /a FAILED1 ) ) ) ) echo. ) ) if exist %TAR_LIST_FILE% del %TAR_LIST_FILE% nul 21 echo echo 全部处理完成 echo echo 总计tar文件%TOTAL% 个 echo 本次成功解压%SUCCESS% 个 echo 本次失败%FAILED% 个 echo 已跳过%SKIPPED% 个 echo 重新解压%REEXTRACT% 个 echo 解压根目录%DEST_DIR% echo echo. pause五、使用前需要修改的地方脚本最前面有三行路径需要根据自己的实际情况修改set SEVENZIP_PATHC:\Program Files\7-Zip\7z.exe set SRC_DIRC:\Users\1\Desktop\1 set DEST_DIRD:\disk8含义如下变量名含义SEVENZIP_PATH7-Zip 的程序路径SRC_DIR存放.tar文件的源目录DEST_DIR解压后的目标根目录如果脚本提示“源目录不存在”需要先检查SRC_DIR对应的文件夹是否真实存在。六、脚本运行逻辑说明1. 检查 7-Zip 是否存在if not exist %SEVENZIP_PATH% ( echo 错误未找到7-Zip请检查路径 echo %SEVENZIP_PATH% pause exit /b )因为脚本依赖 7-Zip 进行解压所以运行前会先判断7z.exe是否存在。如果路径不对脚本会直接停止。2. 检查源目录是否存在if not exist %SRC_DIR% ( echo 错误源目录不存在 echo %SRC_DIR% pause exit /b )源目录就是存放.tar文件的文件夹。如果这个目录不存在脚本不会继续执行。3. 检查目标盘符是否可访问set DEST_DRIVE%DEST_DIR:~0,3%这一句会从目标路径中截取盘符。例如DEST_DIRD:\disk8那么DEST_DRIVED:\然后脚本会检查这个盘符是否存在if not exist %DEST_DRIVE% ( echo 错误目标盘符不存在或不可访问 echo %DEST_DRIVE% pause exit /b )这样可以避免目标盘没有挂载、移动硬盘没插好、盘符变化等问题。4. 统计 tar 文件总数set TOTAL0 for %%f in (%SRC_DIR%\*.tar) do ( if exist %%f set /a TOTAL1 )这里会统计源目录中有多少个.tar文件。如果一个都没有找到会提示未找到任何tar文件5. 每个 tar 文件解压到同名目录核心逻辑是set OUT%DEST_DIR%\%%~ni其中%%~ni表示 tar 文件名不包含扩展名OUT表示最终解压目录。例如C:\Users\1\Desktop\1\disk8_backup.tar会解压到D:\disk8\disk8_backup这样做的好处是不会把所有 tar 文件直接混在一个目录下而是每个 tar 包都有单独的输出文件夹。七、文件数量校验逻辑这个脚本不是简单地“发现 tar 就解压”而是先做文件数量判断。1. 统计 tar 包内部文件数量%SEVENZIP_PATH% l -slt %%i %TAR_LIST_FILE% 2nul这句会使用 7-Zip 列出 tar 包内部文件信息并写入临时文件。然后通过findstr /c:Folder - %TAR_LIST_FILE% | find /c /v 统计 tar 包内部的文件数量。这里统计的是文件不包含文件夹。2. 统计目标目录已有文件数量dir /a-d /b /s !OUT! 2nul | find /c /v 这句会递归统计目标目录中已有的文件数量。其中参数作用/a-d只统计文件不统计文件夹/b使用简洁输出/s递归统计子目录find /c /v 统计行数也就是文件数3. 判断是否需要解压判断逻辑大致是如果存在 _extract_done.flag 直接跳过 否则 如果目标目录文件数 tar 内部文件数 认为已经解压完成跳过并补写完成标记 否则 执行解压也就是说这个脚本可以处理几种情况情况脚本行为目标目录不存在创建目录并解压目标目录为空开始解压目标目录已有部分文件继续解压目标目录文件数量已经满足跳过已经存在_extract_done.flag跳过八、关于“重新解压”的理解脚本中有一行提示状态目标目录文件数量不足重新解压这里的“重新解压”并不是指先删除原来的文件然后从头覆盖一遍。因为实际解压命令是%SEVENZIP_PATH% x %%i -aos -o!OUT! nul 21其中-aos的含义是Skip extracting of existing files也就是跳过已经存在的文件。所以如果目标目录里已经有一部分文件脚本再次运行时已经存在的文件不会被覆盖缺失的文件会继续解压可以理解为一种“续解压”。这一点对大批量小文件非常重要因为如果每次都从头覆盖会非常浪费时间。九、完成标记文件的作用解压成功后脚本会在目标目录中写入_extract_done.flag例如D:\disk8\disk8_backup\_extract_done.flag文件内容大概包括完成时间 源文件 解压目录 tar内部文件数 解压后文件数 标记来源它的作用是表示该 tar 包已经解压完成下次运行脚本时可以快速跳过方便后期排查这个目录是从哪个 tar 文件解压出来的。十、运行效果示例运行时会显示类似下面的信息 批量解压TAR文件 - 文件数量校验版 源目录 : C:\Users\1\Desktop\1 目标根目录 : D:\disk8 目标盘符 : D:\ 找到tar文件总数1 开始检查并解压处理...处理单个 tar 文件时会显示 已处理 1/1 进度 100% 正在检查disk8_backup.tar 解压目录D:\disk8\disk8_backup tar内部文件数53540955 目标目录文件数17576208 状态目标目录文件数量不足重新解压如果最后成功会显示解压后文件数53540955 状态解压成功文件数量校验通过全部完成后会输出统计结果 全部处理完成 总计tar文件1 个 本次成功解压1 个 本次失败0 个 已跳过0 个 重新解压1 个 解压根目录D:\disk8 十一、需要注意的问题1. 这个脚本适合 tar 包不适合所有压缩格式当前脚本只会处理*.tar如果要处理.zip、.7z、.tar.gz需要修改匹配规则和解压逻辑。2. 文件数量校验不是百分百严格校验脚本采用的是“文件数量校验”也就是目标目录文件数量 tar 内部文件数量就认为基本解压完成。这种方法比较快也适合大量小文件场景。但是它并不会逐个校验文件名是否完全一致文件大小是否完全一致文件内容是否损坏文件哈希是否一致。所以它适合一般批量解压和断点续解压场景但不适合对数据完整性要求极高的场景。如果需要更严格的校验可以进一步增加文件清单比对或哈希校验。3. 大量小文件会非常慢如果 tar 包中包含几千万个小文件即使每个文件只有几 KB统计文件数量也会非常慢。尤其是下面这句dir /a-d /b /s !OUT! | find /c /v 它需要递归遍历目标目录下的所有文件。所以如果目标目录中文件数量非常多脚本看起来可能会“卡住”但实际上可能是在统计文件数量。4. 目标磁盘状态很重要如果目标硬盘存在以下问题文件系统错误坏道I/O 错误磁盘碎片严重无法创建新文件夹无法写入新文件那么脚本可能会出现解压失败长时间无响应文件数量不足无法创建完成标记可以读文件但不能写文件。这种情况就不是脚本本身的问题而是磁盘或文件系统状态可能已经异常需要优先检查硬盘。十二、适用场景这个脚本比较适合以下场景Windows 下批量解压.tar文件tar 包数量较多每个 tar 包内部文件数量很多解压过程可能中断希望重复运行脚本时自动跳过已完成任务希望尽量避免重复覆盖已有文件需要简单判断是否解压完整。十三、总结这次脚本的核心思路是批量遍历 tar 文件 → 为每个 tar 创建同名解压目录 → 统计 tar 内部文件数量 → 统计目标目录已有文件数量 → 判断是否需要解压 → 使用 7-Zip 的 -aos 参数跳过已有文件 → 解压成功后写入完成标记相比直接手动解压这种方式的好处是可以批量处理可以断点续解压可以避免重复覆盖可以通过文件数量做一个简单校验可以重复运行脚本而不用担心所有文件从头再来。