那天处理一块外置硬盘时,最先看到的是一个很有压力的数字:容量大约 908G,使用率已经到 96%,只剩下约 37G。用户指出其中两个最大的目录,一个约 320G,另一个约 177G,希望找出重复文件,也看看有没有明显的临时内容和长期不会再用的东西。
这类任务很容易让人直接进入“删什么”的思路。空间告急,眼前最大的目录又已经被点名,似乎只要把旧文件、缓存和重复副本清掉,问题就解决了。但我后来发现,真正要处理的不是几个大目录,而是一个同时涉及路径、进程、文件引用和恢复可能性的判断问题。
空间不足时,第一步不是删除,而是先确认自己正在处理哪一个设备、哪一类数据。
先找到目标,再谈清理
当时的第一个要求,是让清理入口可以根据设备名称定位目标。这个细节看起来像是为了方便,实际是在降低操作边界不清的风险。同一个目录名可能出现在不同硬盘、不同工作机,甚至不同的挂载卷上。如果只凭当前看到的路径下手,操作对象一旦判断错,后面所有审计和清理都会建立在错误基础上。
所以流程先做名称解析:输入一个目标名称,得到它对应的设备和卷,再继续进行只读检查。名称有歧义时列出候选,名称不存在时提示相近目标,而不是悄悄选择一个最像的结果。这个动作没有腾出任何空间,却先把“我到底在动谁”这件事固定下来。
如果不处理这一步,会导致一个很危险的错觉:命令执行成功了,空间也可能发生变化,但变化发生在错误的盘上。尤其外置盘、备份盘和工作盘的目录结构常常相似,成功运行不等于目标正确。
先看正在运行的东西
目标确认后,我没有立即扫描“看起来最旧”的目录,而是先识别正在被使用的内容。一个名字带有归档意味的脚本目录,实际上仍被后台守护进程调用;另一个运行目录里,产线正在处理一部影片。它们都可能看起来像历史文件或中间产物,但这次不能动。
这里最容易误判的是目录名称。归档不代表已经退出工作流,旧日期不代表没有进程打开,体积很大也不代表可以优先处理。文件管理器看到的是静态目录,进程看到的是仍然有效的依赖关系。两者不一致时,应该相信正在运行的状态,而不是相信名字。
如果把产线目录当成普通缓存挪走,正在执行的任务可能读不到素材、写不出中间结果,甚至留下一个很难判断是否完整的半成品。如果把后台进程仍在使用的脚本目录改名,影响可能不会立刻出现,却会在下一次守护进程重启时暴露。
目录是否能清理,不能只看它占了多少空间,还要看现在有没有工作依赖它。
重复文件先做 dry-run
在排除运行中目录后,下一步是对两个大目录做审计和重复扫描。这里的关键不是“找到重复文件”,而是先让扫描结果停留在报告阶段。dry-run 的价值,是把判断和执行分开:先知道有哪些组、每组涉及哪些路径、预计能节省多少,再决定是否进入改变磁盘状态的步骤。
扫描最后发现 146 组可以处理的重复文件。它们不是凭文件名判断相同,而是根据内容确认完全一致。这个区别很重要,因为“同名”只能说明它们可能来自同一份素材,“同内容”才说明它们具备共享底层数据的条件。
最容易走的错误捷径,是看见同一个文件出现多次,就直接删掉较旧的那份。这样虽然动作简单,却可能破坏某个程序依赖的原路径,也可能把不同版本的上下文误当成同一份数据。即使内容相同,路径本身也可能有价值。
我选择先做文件系统层面的克隆合并,是因为它保留了每个文件原来的名字和路径,只让相同内容共享底层数据。可以把它想成多本完全相同的书共用同一个印刷底稿:每本书仍然放在原来的书架上,程序照样可以按原路径打开;只有未来某一本被修改时,系统才为变化部分单独保存数据。
正式执行后,实际节省约 125G。这个结果说明,空间问题不一定要靠删掉可见的文件来解决。先消除物理层面的重复,既能得到明显收益,又没有把路径引用和恢复选择一起拿走。
冷缓存要进隔离区
重复合并之后,才轮到处理长期没有使用的缓存。这里我把“可清理”拆成了两个条件:它确实属于可重建数据,并且最近没有持续写入或被当前流程依赖。满足条件的内容先移入废纸篓或隔离区,不直接删除。
这次隔离的冷缓存约 77G,包括长期未使用的构建缓存、地理数据缓存、语言工具缓存,以及软件更新包等。近 30 天仍有写入的几类缓存没有碰,因为它们虽然体积不小,却还处在活跃状态。剪辑产线里的旧样片也没有直接处理,而是保留给对应工具再核对。
我选择隔离而不是直接删除,是因为缓存的价值不在内容本身,而在它能不能被重新生成、重新下载,以及谁还在依赖它。只要不能确认这 3 件事,就应该留下退路。移入废纸篓后,目录通常还占着空间,但至少有一个明确的恢复入口,也不会把所有历史废纸篓内容一并清空。
这里发生过一个很小却很有提醒意义的错误:一次移动过程中,构建工具的配置目录被误判为缓存的一部分。发现后立即放回原处,配置文件没有被留在隔离区。它让我更确定,缓存和配置不能按相邻位置或相似名称判断。缓存可以重建,配置往往保存的是本机工作方式,不能因为它很小就忽略。
可逆的隔离不是拖延,而是给不确定的判断保留一次纠错机会。
把清理变成一条判断链
这次之后,我把流程整理成 4 个连续问题。先问“目标设备是否确认”,再问“哪些目录正在被进程使用”,接着问“哪些重复内容可以在不改路径的情况下合并”,最后才问“哪些冷缓存可以移入隔离区”。每一步都要留下报告,下一步只处理前一步已经确认过的范围。
这条顺序的好处,是把不同风险分开了。设备定位解决对象风险,运行状态解决业务中断风险,重复合并解决空间收益和路径稳定性的平衡,隔离区解决删除不可逆的风险。若把它们揉成一个“清理大盘”的动作,任何一个误判都会被后续步骤放大。
如果空间仍然不够,再把彻底删除作为单独的人工动作。那时要明确删除的批次、确认隔离区里只有这一批内容,并接受删除后无法恢复的结果。不能因为前面已经做得很保守,就顺手把最后一步也自动化;风险性质已经变了。
这件事让我重新意识到,工具真正改变的不是删除速度,而是能不能把判断过程保存下来。一个流程成熟的标志,不是它能在一次操作中清出多少空间,而是下一次遇到类似问题时,仍然知道先确认什么、哪些东西不能碰、哪里必须留下退路。
下次我会怎么做
下次遇到大硬盘告急,我会先用设备名称确认目标,再做只读审计,不从最大的目录开始盲删。审计时先标记正在被守护进程、编辑器或产线使用的目录,把它们从自动处理范围中排除。然后对剩余范围做重复扫描,先看 dry-run 报告,再优先选择不改变路径的合并方式。
对于缓存,我会先按“可重建、长期未使用、没有配置性质”筛选,再整体移入带批次标记的隔离区。隔离后不急着清空废纸篓,先观察工作流是否正常,确认没有程序报错、没有任务缺素材,再由用户单独决定是否彻底删除。
最终我想保留的不是一套“看到大文件就删”的经验,而是一条可以复用的规则:先确认对象,再保护运行中的依赖;先用不改路径的方式消除重复,再把明确的冷缓存隔离;不可逆删除永远放到最后,并且由人明确承担。