跳过正文

整机备份换 7z 非固实:列出文件从好几分钟到 0.59 秒

·4040 字·9 分钟
目录

重装系统前把整个用户目录(AppData)打成一个「按日期命名的整包备份」RAR,事后想取回个别文件时发现:打开包、看文件列表都要先把全档扫一遍,好几分钟起。改成 7z 非固实重打包后,列表 0.59 秒出、单文件可直接提取,顺带裁剪掉约 41 GiB 的缓存与可重装内容。适用环境:Windows 11、WinRAR 7.23、7-Zip 22.01,2026 年 8 月实测。

一、症状与第一手数据
#

重装系统前,原始包是对「系统盘用户目录」做的整包备份:实测当时目录 28.2 万个文件、34.6 GB。打包本身没问题,问题出在事后取用——想打开备份看一眼清单、或取出其中某个配置文件,工具都要先把所有文件过一遍,明显等不起。

第一手数据(对备份包实测):

  • 压缩后体积 36.3 GB,内部是按日期命名的 RAR5 归档;
  • 完整清单统计:516,602 个文件 / 64.87 GiB(解压后 69.65 GB);
  • 读这份清单(包含列目录、解压)耗时:好几分钟

这不是压缩率的问题——体积 36 GB 对整机用户目录完全可以接受。真正的问题是容器格式的取舍

新旧包对比:

项目 旧包(RAR) 新包(7z)
格式 非固实 RAR5,无中央目录 7z 非固实(-ms=off),集中文件头
压缩后体积 36.3 GB 13.1 GB
原始数据体积 64.87 GiB 24.0 GiB
文件数 516,602 62,936(12,615 个文件夹)
打开文件列表 扫描全档,好几分钟 0.59 秒(实测 0.588 秒)
取单个文件 顺序读取相关区块 直接定位,即时取出
完整性校验 参考用 Everything is Ok

二、根因:容器格式的取舍,不是压缩率
#

先核对备份包的属性:头部只有「RAR 5, 恢复记录」,没有固实标记——这个包本身是非固实的。所以打开慢的根源不是固实,而是 RAR 没有中央目录

  • 打开文件列表,工具要从头顺序扫描数据流里的 51.6 万条文件头才能拼出清单;
  • 固实模式是另一层成本:所有文件被作为一个块压缩,取中间某个文件时,必须先解出排在它前面的全部内容(7z 默认就开固实)。RAR 勾了固实时同样如此。

三种主流格式的差异:

特性 RAR ZIP 7z
中央目录(打开即见全部清单) 无,需顺序扫描 有,集中在文件尾 有,集中在头部
固实模式 可选(勾了才开) 通常关 默认开
固实时取单个文件 先解出它前面所有文件 同左 同左
非固实时取单个文件 直接取 直接取 直接取

固实的收益是压缩率更高(小文件多、彼此相似时尤其明显),代价是随机取用极慢。RAR 的设计初衷是「整体解压」——恰好和这台机器的使用场景相反:整机用户目录备份的真实用途,是以后偶尔捞出某个配置、存档、聊天记录,不是整套恢复

按用途选格式:

  • 要整体分发、长期静置 → 固实(RAR 或 7z 都行),压缩率优先;
  • 事后随机取文件 → 7z 关固实(每文件独立压缩 + 集中文件头)或非固实 ZIP。ZIP 兼容性最好,7-Zip 免费且压缩率更好。

还有一个旁路:干脆不打包,直接复制成普通文件夹,浏览、搜索、单文件恢复全部瞬时,还能保留时间戳与 ACL:

robocopy "%USERPROFILE%\AppData" "数据盘:\Backup\AppData" /E /XJ /MT:16 /R:1 /W:1 /COPY:DAT

本例没有走这条路:明文目录会被快捷启动类工具的索引扫到、还会把文件列表弄脏。保持归档形态,只做「裁剪 + 换格式」。

三、处置:先分析清单,再裁剪,最后换格式重打包
#

3.1 全量解压,但先读清单、做体积分布分析
#

不能凭印象删 64.87 GiB 的东西。先用 WinRAR 命令行导出完整清单(GBK 编码、51.6 万行),再用脚本按目录聚合体积与文件数分布:

"C:\Program Files\WinRAR\Rar.exe" l -v "外置盘:\整包备份-20260827.rar" > 清单.txt

分析一出,垃圾大头立刻现形:显卡驱动残留、pip/npm/uv 缓存、可重装软件本体、一堆 *-updater 下载缓存、Temp 与崩溃转储。接着全量解压(后台跑,-mmt 多线程):

"C:\Program Files\7-Zip\7z.exe" x -y "外置盘:\整包备份-20260827.rar" -o"D:\AppDataTrim\extract" -mmt=on

结果与清单一致:Everything is Ok,60,811 个文件夹 / 455,791 个文件 / 69.65 GB。

3.2 裁剪清单:一类一类删,标准只有一条
#

判断标准可以浓缩成一句:可重装的、可再下载的、纯缓存与日志的,删;不可再生的,留。逐类过:

类别 典型内容 判断标准
显卡驱动残留 NVIDIA/AMD 本地组件与着色器缓存(Local/LocalLow)、D3DSCache 重装系统或更新驱动后自动重建,纯残留
包管理器缓存 pip 约 3.0 GB、npm-cache 约 1.6 GB(7.8 万个文件)、uv 约 1.1 GB 随时可以重新下载;删缓存不影响已装包
可重装软件本体 Local\Programs 安装目录 4.9 GB、包管理器安装缓存 重装可得,备份里留它等于白背一遍
浏览器与旧版工具数据 浏览器整个目录、旧版自动化工具数据目录 本例已在新系统恢复完毕,确认后整目录删除
微软各类缓存 WinGet(0.64 GB)、OneDrive(0.52 GB)、Office 组件包(0.63 GB)、RDP 缩略图、浏览器缓存类 全部是缓存与组件包,重登/重装后再次生成
UWP 系统包 Packages 下微软商店与系统包 可自动重装;WSL 发行版是例外,见保留清单
临时目录与崩溃转储 Temp、CrashDumps 纯垃圾
自动更新器下载缓存 各类 *-updater 目录合计约 2.4 GB、游戏平台 HTML 缓存、在线音乐客户端缓存 更新完成即失效,重装后重新下载

裁剪脚本实测单轮释放 16.09 GiB、229 个条目;再算上整目录删除与两处「移出」(见下),原始数据从 64.87 GiB 降到 24.0 GiB,约 41 GiB 消失,文件数从 51.6 万降到 6.3 万。

保留清单(按不可再生性,反着过的):

  • 邮件客户端的邮件库——账号、邮件、签名,重装后几乎无法重建;
  • 聊天记录——IM 本地数据与收发过的文件;
  • 输入法配置——用户词典、皮肤与方案,重装后难以原样找回来;
  • 游戏存档——LocalLow 下各工作室的存档目录,游戏可重装、进度不能;
  • WSL 发行版磁盘镜像——一个发行版约 3.8 GB,之后可用 wsl --import 恢复;
  • 用户字体——本例 142 个字体文件直接「归位」到新系统用户字体目录并注册 HKCU(663 个字族,无需重启生效),不再进备份包;
  • 密码管理器、代理软件、SSH 客户端、快捷启动工具、远程控制软件的配置——量小、不可再生。

3.3 过程事故:重写脚本时弄丢一个 keep 判断
#

裁剪脚本中途被重写过一次(为纳入「字体移出、浏览器整删」两个调整),重写时 delete_children丢了 keep 判断——结果把用户明确要求保留的 WSL 发行版包(3.83 GB)当成「非 WSL 系统包」删掉了。脚本输出里赫然列着这条误删记录。

处置:原始包原封未动,直接从它重新提取这个包,指定路径、不动其他内容:

"C:\Program Files\7-Zip\7z.exe" x -y "外置盘:\整包备份-20260827.rar" -o"D:\AppDataTrim\extract" "AppData\Local\Packages\<WSL发行版目录>\*"

恢复 3.83 GiB 并核验结构通过,无数据损失。中间还有个插曲:第一次提取报「找不到文件」,一度以为原始包丢了——核对磁盘列表后确认只是外置盘重新插拔后盘符变了,改一下命令里的盘符即恢复。

教训,两条都值钱:

  1. 任何「批量删除」脚本,先 dry-run:只列清单、不执行,人工过目一遍再放行;
  2. 原始包保留到新版验收通过为止——这次如果没有原封未动的原包,3.8 GB 的 WSL 磁盘镜像就真的没了。

3.4 换格式重打包:7z 非固实
#

对裁剪后的目录重打包,命令原样:

cd /d/AppDataTrim/extract
"C:\Program Files\7-Zip\7z.exe" a -t7z "外置盘:\整包备份-20260827_trimmed.7z" AppData -ms=off -mx=1 -mmt=on -mhc=on

三个参数的含义:

  • -ms=off——关闭固实,每个文件独立压缩,随机取用无需前置解压;
  • -mx=1——压缩级别 1(快、省内存;对本就高度压缩的缓存/数据库类数据影响不大);
  • -mhc=on——开启头压缩,文件头块紧凑,打开时读取更快。

打包耗时约 7 分钟(约 1 GB/分钟),产出 13.1 GBEverything is Ok

四、验证
#

验收看四个可观察指标,全部通过:

  1. 打开列表速度time 7z l 包名.7z 实测 real 0m0.588s——对照旧包的好几分钟;输出确认 62,936 个文件、12,615 个文件夹。
  2. 完整性校验7z t 全量读取 13 GB,Everything is Ok、EXIT=0,Size 25.7 GB → Compressed 13.1 GB 与打包日志一致。
  3. 裁剪结果对账Packages 下只剩 WSL 发行版;邮件库、聊天记录、输入法、游戏存档、工具配置等保留项逐一确认存在;字体已在新系统生效。
  4. 取单个文件:非固实下按路径直接指定解压即可,不依赖任何前置内容——这本来就是换格式的目的。

怎么判断「没解决」:列清单仍要数秒以上、7z t 报错、任一保留项缺失、取出的文件与原始目录不一致——出现任意一条都要回到第三步查脚本。

收尾:原包先不删,新包验收通过后再处理,可腾出 36 GB;24 GB 的解压临时副本清理掉,分析脚本与清单保留备查。

五、留给后来者的清单
#

  • 按取用方式选格式:随机捞文件的备份用 7z 非固实(-ms=off)或非固实 ZIP;整体分发才用固实。
  • 打开慢先查两件事:有没有中央目录(RAR 没有,ZIP/7z 有)、有没有开固实(7z 默认开)。两者都会让「看清单/取单文件」退化成全档扫描。
  • 裁剪先分析后动手:先用命令导出完整清单做体积分布,一类一类过;删除标准就一句「可重装、可再下载、纯缓存 → 删」。
  • 先归位再删除:字体、WSL 这类要保留的,先复制/导入到新系统,再从备份里移除,账目才对得上。
  • 批量删除脚本的纪律:先 dry-run 只列清单;keep 判断做成显式白名单,改名/重写脚本时逐行核对;原始备份保留到新版验收通过。
  • 同场景可直接抄pip cache purge/npm cache clean --force/uv cache clean 之外,那些 *-updater 目录和 TempCrashDumps 是每台 Windows 机器都有的同款垃圾。
  • 再打包命令模板(本轮实测校验过):导出清单 → 解压 → 裁剪 → 7z a -t7z "外置盘:\整包备份-…_trimmed.7z" AppData -ms=off -mx=1 -mmt=on -mhc=on7z t 全量校验,一条流水线下来,最后清理解压与清单的临时文件。

六、碎碎念
#

这台机器最大的收获不是省下的几十 GB,而是想明白「备份格式要跟着取用方式走」。整包归档适合一次性整体恢复,而整机用户目录备份的真实身份是「数据保险库」——平时不碰,偶尔开柜子拿一件东西。保险库的门,不该每次开都重新搬一遍全馆。

至于那次误删,事后看完全是纪律问题:重写脚本时「顺手」丢了条件判断,没有 dry-run 就执行。原包原封未动是最后的兜底,但兜底不应该成为常态。先列清单,再动手删——这句话值得贴在每个批量操作脚本的第一行注释里。