主实例迁移完成后,旧主机上往往会留下大量重复文件。

这些文件看起来像“迁移残留”,但不能直接删除。因为旧主机上可能同时保留着几类不同性质的数据:

- 已经完整迁移到新主机的重复文件
- 两边同名但内容不同的文件
- 只存在于旧主机、尚未迁移的文件
- 因容量或性能原因故意保留在旧主机的大型项目
- 浏览器/CDP 等扩展能力目录

如果不加区分地删除旧工作区,很容易误删尚未迁移的项目、迁移后仍需要的扩展资源,或者旧主机上独有的备份文件。

因此,迁移后的文件清理不能靠“看目录名猜”,而应该靠审计结果决定。

本篇记录的是一次通过相对路径、文件大小和 sha256 hash 对比,安全删除旧主机重复文件的过程。

清理前的基本局面

迁移完成后,系统已经形成新的主从结构:

新主机:
- OpenClaw 主实例
- 主工作区
- 主状态目录
- 消息通道和 gateway

旧主机:
- 不再作为 OpenClaw 主实例
- 仍保留部分扩展资源
- 仍保留一个因容量原因没有迁移的大型项目目录
- 仍保留浏览器/CDP 专用目录

旧主机上的大部分工作区文件已经迁移到新主机,但不是全部。

其中有一个大型项目目录因为新主机存储容量不足,暂时继续保留在旧主机上,作为扩展项目使用。另一个浏览器/CDP 目录也属于外部工具资源,不属于本次工作区清理范围。

因此,清理前必须先确定排除范围。

不能清理的目录

迁移后文件清理首先要明确两类禁止触碰目录。

第一类是大型项目目录。

它因为容量原因没有迁移到新主机,仍然需要继续保留在旧主机上。如果清理脚本把它当成普通迁移残留,就会造成严重误删。

可以抽象表示为:

<old-workspace>/projects/<large-project>

第二类是浏览器/CDP 专用目录。

这个目录用于远程浏览器能力,属于旧主机作为扩展资源主机的一部分,不是旧 OpenClaw 主实例残留。

可以抽象表示为:

<desktop-cdp-dir>

因此,清理审计范围应该是:

对比旧工作区和新工作区
但排除大型项目目录
并且完全不触碰浏览器/CDP 目录

这个边界非常重要。否则“清理旧工作区”很容易被误解成“删除旧主机上所有 OpenClaw 相关目录”。

为什么不能直接用 rsync –delete

迁移清理中,rsync --delete 看起来很诱人。它可以让两个目录快速变成一致状态。

但在这个场景中,它并不适合。

原因是旧主机上故意保留了一些新主机没有的内容。如果直接用 rsync --delete 或类似逻辑,就可能把旧主机独有但仍然需要的文件删除。

尤其是以下几类文件:

- 新主机没有的大型项目
- 旧主机专用的扩展目录
- 迁移归档
- 旧服务备份
- 本地虚拟环境中特殊文件
- 迁移后内容已经分叉的规则或记忆文件

因此,本次清理不追求两个工作区完全一致,而是只删除那些已经被确认“新主机上有同名文件,且内容完全相同”的文件。

这比 rsync --delete 更保守,也更适合迁移后的分层清理。

审计方法:相对路径、大小和 sha256

安全清理的核心是生成两边文件清单。

对旧主机工作区生成 manifest:

相对路径
文件大小
sha256 hash

对新主机工作区也生成同样的 manifest。

然后按相对路径进行对比。

相对路径一致、大小一致、sha256 一致,才能认定为完全重复文件。

判断逻辑如下:

旧主机有,新主机也有
相对路径相同
文件大小相同
sha256 相同
=> 可作为删除候选

如果只是文件名相同,但 hash 不同,就不能删除。

如果旧主机有,新主机没有,也不能删除。

如果新主机有,旧主机没有,只作为参考,不影响旧主机清理。

这种审计方式的好处是:

- 不依赖文件修改时间
- 不依赖目录名猜测
- 不依赖主观判断
- 能准确识别真正重复文件
- 能把差异文件单独列出复查

文件修改时间在迁移中不一定可靠。新复制的旧文件可能有新时间戳,旧主机上被触碰过的文件也可能只是 metadata 变化。因此,hash 比 mtime 更适合作为删除依据。

四类结果

审计完成后,文件被分为四类。

第一类:旧主机和新主机完全一致。

旧主机存在
新主机存在
大小相同
sha256 相同

这一类是删除候选。

第二类:两边都有,但内容不同。

旧主机存在
新主机存在
相对路径相同
大小或 sha256 不同

这一类不能直接删,需要复查。

第三类:只在旧主机存在。

旧主机存在
新主机不存在

这一类默认保留。

第四类:只在新主机存在。

新主机存在
旧主机不存在

这一类只是参考,通常不影响旧主机清理。

通过这种分类,清理对象被严格限制在第一类,也就是“新主机已存在且内容完全一致”的文件。

审计结果

本次审计结果如下:

旧主机检查文件数量:67406
新主机检查文件数量:67395
完全一致、可作为删除候选:67325
两边不同、需要复查:70
只在旧主机、必须保留:11
只在新主机:0
读取错误:0

同时确认:

大型项目目录已排除
浏览器/CDP 目录未触碰

这个结果说明,大部分旧主机文件已经完整迁移到新主机,可以安全清理。
但仍然有 70 个差异文件和 11 个旧主机独有文件,不能混入删除操作。

为什么 70 个差异文件不能直接删

70 个差异文件虽然数量不多,但反而更需要谨慎。

它们可能包括:

- 迁移后在新主机继续更新的规则文件
- 迁移后在新主机继续追加的记忆文件
- 两边路径相同但内容轻微不同的配置文件
- 脚本中因为路径差异导致 hash 不同的文件
- 虚拟环境中的激活脚本或配置文件

这类文件不能简单按“旧主机已经不是主实例”就全部删除。

例如,规则文件在新主机上可能已经更新,旧主机版本落后。此时旧主机文件可以删,但必须先确认它不是旧主机独有修改。

反过来,也可能有一些文件在旧主机上被手动更新,但尚未同步到新主机。如果直接删除,就会丢失内容。

因此,差异文件应该进入下一轮复查,而不是本轮删除。

为什么 11 个旧主机独有文件也不能直接删

只在旧主机存在的文件更不能直接删除。

它们可能包括:

- 旧服务备份
- 迁移前归档
- 本地虚拟环境中的特殊可执行文件
- 没有迁移到新主机的残留但仍可能有恢复价值的文件

其中如果存在大体积迁移归档,后续可以考虑删除以释放空间。但这应该是单独决策,而不是和重复文件一起删除。

清理策略应该是:

重复文件:本轮删除
差异文件:复查后处理
旧主机独有文件:单独判断用途和价值

分阶段处理可以显著降低误删风险。

删除前必须 dry-run

即使已经有审计列表,真正删除前仍然需要 dry-run。

dry-run 的目的不是再次计算 hash,而是确认删除程序将要删除的数量和范围与审计结果一致。

例如:

审计删除候选:67325
dry-run 准备删除:67325

两者一致,才继续执行。

如果数量不一致,就说明列表、路径、排除规则或脚本逻辑存在问题,必须停止。

dry-run 还应该确认:

- 删除对象都在旧工作区内
- 不包含大型项目目录
- 不包含浏览器/CDP 目录
- 不包含差异文件列表
- 不包含旧主机独有文件列表

这一步是把“审计正确”和“删除脚本正确”分开验证。

删除执行:只删列表内文件

真正删除时,只允许删除审计生成的候选列表中的文件。

关键规则是:

- 只按候选列表删除
- 路径必须限制在旧工作区内
- 不删除整个旧工作区
- 不使用 rm -rf 旧工作区
- 不使用 rsync --delete
- 不删除差异文件
- 不删除旧主机独有文件
- 不触碰排除目录

这类清理最怕“为了省事”扩大范围。

正确做法是逐条读取候选列表,把相对路径拼接到旧工作区根目录下,确认路径没有逃逸,再删除对应文件。

即使候选文件数量很多,也不要把操作简化成删除整个目录后再恢复保留项。那样风险更高。

删除后的复查

删除完成后,需要再次复查几个关键点。

本次复查结果如下:

删除候选文件:67325
实际删除文件:67325
候选删除后复查:现存 0 个
差异文件:70 个全部仍然存在
旧主机独有文件:11 个全部仍然存在
读取/删除错误:0

同时再次确认:

大型项目目录仍然存在,未被触碰
浏览器/CDP 目录仍然存在,未被触碰

这说明删除只作用于完全重复文件,没有误伤保留范围。

清理空目录

文件删除后,旧工作区里会留下大量空目录。

这些空目录本身不一定有害,但会让目录结构看起来仍然庞大,也会给后续判断带来干扰。

因此,可以在删除文件后清理空目录。

但空目录清理也要遵守排除规则:

- 不能进入大型项目目录清理
- 不能触碰浏览器/CDP 目录
- 只能清理本轮删除后产生的空目录
- 不删除仍包含保留文件的目录

本次清理了大量空目录:

空目录清理:8269 个

这说明迁移重复文件删除后,旧工作区结构已经大幅收缩。

释放空间结果

删除前后可用空间变化如下:

删除前可用空间:311,594,889,216 bytes
删除后可用空间:320,968,237,056 bytes
净增加空间:9,373,347,840 bytes

约等于:

9.37 GB
约 8.73 GiB

这个结果说明,大部分可释放空间来自已经迁移到新主机的重复文件,而不是必须保留的大型扩展项目。

这也是审计清理的价值:既释放了空间,又没有破坏旧主机仍承担的扩展角色。

为什么不一次性清完

这次清理结束后,旧主机上仍然保留两组文件:

70 个差异文件
11 个旧主机独有文件

这不是清理失败,而是安全策略的一部分。

文件清理应该分层进行:

第一轮:
删除 hash 完全一致的重复文件

第二轮:
复查差异文件,判断哪边是新版本

第三轮:
复查旧主机独有文件,判断是否仍有保留价值

第四轮:
处理归档、大文件和旧备份

一次性清理所有“看起来像残留”的文件,短期省事,长期风险更高。

尤其在 AI 代理工作区里,memory、rules、output、plans、projects 都可能有长期意义。不能只看路径名称就决定删除。

清理后的状态

这一轮完成后,旧主机工作区变成了更明确的扩展资源目录,而不是主工作区的完整副本。

状态可以概括为:

已删除:
- 新主机已有且 hash 完全一致的重复文件

仍保留:
- 大型项目目录
- 浏览器/CDP 目录
- 70 个差异文件
- 11 个旧主机独有文件

这意味着旧主机不再承担完整工作区备份角色,只保留仍需人工判断或明确需要继续存在的内容。

经验总结

这次清理的核心经验有三个。

第一,迁移后的清理必须有排除边界。

不是所有旧主机上的 OpenClaw 相关目录都该删除。
扩展项目和浏览器/CDP 目录可能仍然是有效资源。

第二,重复文件必须用 hash 确认。

相对路径相同不够。
文件大小相同也不够。
sha256 一致才可以作为删除候选。

第三,删除必须分阶段。

先删完全一致文件。
再看差异文件。
最后判断旧主机独有文件。

这种方法比手工猜测更慢,但安全得多。

小结

迁移后的文件清理,不应该被看作“把旧目录删掉”。

更准确地说,它是一次基于审计的收缩过程:

把旧主机上已经迁移完成的重复文件删除,
把仍然需要判断或保留的文件留下,
让旧主机从完整主工作区副本变成明确的扩展资源节点。

本次清理通过相对路径、文件大小和 sha256 hash 对比,确认了 67325 个完全重复文件,并安全删除,释放约 9.37 GB 空间。同时,70 个差异文件、11 个旧主机独有文件、大型项目目录和浏览器/CDP 目录都被保留下来。

这说明,迁移清理可以做到既释放空间,又不破坏后续扩展能力。

对本地 AI 代理系统来说,这种方法尤其重要。因为代理工作区往往混合了配置、记忆、项目、输出、脚本、缓存和归档。只有通过审计分类,而不是凭感觉删除,才能让迁移后的清理真正安全。

Leave a Reply

Your email address will not be published. Required fields are marked *