disktree:把主目录画成一张磁盘地图,点几下就能清出几十 GB

硬盘又满了。这是每个开发者的月度循环:删几个 node_modules,清一下 Docker,重启,然后下个月再演一遍。问题是,你其实从来没真正知道「到底是什么在占地方」——直到你装上一个会把答案画出来的工具。

disktree 就是干这个的。它是 tobi 在 9 月 24 日建仓、专门为 Omarchy 写的磁盘可视化工具,两天冲到 900 多星。默认扫描你的主目录,把每一个目录画成一块按真实磁盘占用缩放的嵌套马赛克(treemap,矩形树图)——你一眼就能看出哪个文件夹是大象,哪个是蚂蚁。

它最好的一点,是它不急着帮你删东西。你可以随便标记,但直到你走进「复查」页面并按下确认之前,什么都不会发生;而永久删除那条路,永远会先问一次。

disktree 界面:一个主目录被画成按数据类型着色的矩形树图,可回收空间用斜线标出,右侧面板显示选中项、建议清理项和磁盘剩余空间
主目录画成一张矩形树图:颜色代表数据类型,斜线代表「这块可以拿回来」,右侧是选中项和磁盘剩余空间。

它是怎么「看」磁盘的

打开 disktree,结构是这样的:

  • 顶部是从 / 下来的路径面包屑,以及测量口径:Size(体积)、Files(文件数)或 Age(年龄)、是否包含隐藏文件、是磁盘占用还是表观大小(apparent size),还有当前画到第几层。点面包屑上的 ▾ 会按大小列出同级目录,可以直接横跳。
  • 马赛克就是主体:颜色是数据种类——代码、Agent 临时文件、工具链、同步文件、git、媒体、文档、缓存——整体是低饱和的,层级越深越亮。斜线网格标出的是「可以拿回来」的空间(缓存、同步历史、包缓存、构建产物),跟颜色无关,所以你能用两种维度同时读这张图。顶层目录带一条自己的颜色带和名字条,更深的目录只有一条细标签。
  • 右侧面板显示当前选中的东西:大小(大字号)、占全盘比例、文件数、最后写入时间,如果是个 git 检出还会告诉你——有多少未提交改动、多少个 stash、多少个未推送的提交。下面还有 Worth a look(最值得看看的大块头)、已标记列表,以及磁盘现在剩多少、标记之后会剩多少。

把 Age 模式打开,颜色会变成最后的写入时间,从本周到很久以前——清理「三年没碰过的旧项目」这个动作,瞬间就有了视觉依据。

「测量」这件事,它做得比大多数同类工具认真

磁盘可视化工具很多,但大部分在「数字准不准」上含糊其辞。disktree 把口径写进了 README:

  • 默认用磁盘占用,也就是 st_blocks × 512——这正是 du 报的数,也是文件删掉之后真正会回来的空间。表观大小(ls -l 显示的那个)只是一个开关的距离。
  • 硬链接只算一次。一个 inode 两个名字,成本算一份文件。
  • 默认包含隐藏文件——因为 ~/.cache 往往是整个主目录里最大的东西。符号链接不跟随。
  • 扫描策略参考了 dust:每个根一个 rayon scope,每个目录一个完成计数器(保证没有目录会在它最后一个子目录落地前就被构建),再加一趟自底向上的聚合,顺手去掉重复硬链接。

还有几个细节挺见功力:从 ~ 扫描之后,点面包屑上的 / 或者按 g 可以扩到整块磁盘,但这个扩展是带记忆的——已经量好的子树直接交给更宽的遍历复用,所以从主目录扩到 / 只需要读 ~ 之外的部分(作者说,在这台机器上是「几秒,而不是重新扫一遍」)。旧视图会一直留在屏幕上,直到新树落地,然后自动定位回你原来所在的目录。

另一点:一次扫描只停留在一个卷上,而且「卷」的判定用的是挂载源而不是设备号——因为 btrfs 会给每个 subvolume 独立的 st_dev,所以 /home、/var/log、/var/cache/pacman/pkg 都会被算进去,而 /proc、/sys、/run、tmpfs、/boot、其他磁盘、网络共享和 automount 点会被排除(按路径排除,所以不会为了测量就把 NAS 挂上来)。快照 subvolume 也会被跳过,因为它的文件和活的那些共享数据块,算进去就等于把磁盘算了两遍。

标记、缩放、然后才删除

操作手感是这个小工具真正花心思的地方:

  • 标记用 空格、X 或 回车。被标记的块会变成危险色,它里面的一切也会变成危险色——因为删掉一个目录就是连内容一起删。标记一个目录会吸收掉它内部已有的标记,反向操作会被阻止(会提示你改成取消标记外层目录)。标记永远可以撤销,且节省的空间绝不会被算两遍。
  • 滚轮就是缩放。滚轮会朝指针方向放大,直到指针下的目录填满视图;再滚一档,就直接进入这个目录——整个过程连续,目录内容「长」进画面里。反过来滚就退出去。回车 可以进入任意深度的选中目录,退格 或 Esc 往上退一层。旁边还有一对 < > 在访问过的目录之间前进后退(也支持 alt ← alt →、macOS 上的 ⌘[ ⌘],以及鼠标侧键)。
  • 删除分两条路。按 c(或点 Review…)打开标记清单,取消掉不想删的,然后在两个选项里挑:
    • Move to trash——有回收站时的默认项。macOS 上就是系统「废纸篓」,跟 Finder 的操作完全一样(在别的磁盘上就用那块盘自己的废纸篓;网络共享通常没有)。Linux 上依次尝试 trash-cli 的 trash-put、gio trash、最后是内置的 XDG 回收站。因为可恢复,所以它直接执行,不再确认。
    • Delete permanently——语义等同于 rm -rf。它永远先问一次,而且那个对话框会写清楚「要删什么」和「能拿回多少空间」。

删完之后 disktree 会重新扫描一遍,让屏幕上的数字跟磁盘对得上,并告诉你实际收回了多少空闲空间——这个反馈闭环很多人做工具时会忘。

它拒绝做的事情,比它能做的事情更有意思

一个能对磁盘做 rm -rf 的工具,安全性设计才是它的核心。disktree 的每一条删除规则都写在 crates/disktree-core/src/removal.rs 里,并且每一条都有测试:

  • 只有扫描根目录之下的路径才能被删;
  • 文件系统根、扫描根、你的主目录,一律拒绝;
  • 挂载点拒绝;任何内部含挂载点的目录也拒绝,因为删它会伸进另一个文件系统;永久删除遇到挂载边界也会停下,绝不向下穿越;
  • 内部含有你的主目录或系统树的目录拒绝(macOS 上 /Users 跟 / 在同一个卷上,而 /opt 里住着 /opt/homebrew);
  • 系统树(/usr、/etc、/boot、/var/lib、/nix/store、macOS 和 Linux 上的 Homebrew 前缀……)即使权限允许也拒绝——那些东西归包管理器管,该用的是 pacman、paccache 或 journalctl --vacuum;
  • 符号链接是 unlink,绝不跟随;
  • 任何东西都不会经过 shell——一个名叫 -rf 的文件就只是一个文件;
  • 选中一个 git 检出时也绝不执行它里面指名的程序:调 git 时会关掉 fsmonitor、hooks 和 pager;如果这个检出自己定义了 filter driver,就连状态都不问(显示为「状态未知」)。

这些细节单独看都不起眼,但合起来说明一件事:作者是把它当「会删数据的工具」来写的,而不是当「一个画图的小玩具」。

顺手给 AI 编程智能体也留了个出口

清理动作不一定要自己做。在复查页上,按 s 可以把清单存成一个文本文件(一行一个路径);按 a 则会复制一段给编程智能体用的提示词——大意是:把我挑的这些东西清掉来腾出空间,但每一条路径都要先自己确认(是否存在别处没有的 git 工作、是否有工具自带的清理命令),别碰其他任何东西。

这里有个很漂亮的小设计:名字里带换行的路径会被排除在清单之外,并在提示词里做转义——这样它就不可能伪装成另一条路径混进 AI 的待删列表。考虑到现在很流行「让 Agent 帮你干系统活」,这种防御性写法值得抄。

三个平台,三套「正确答案」

disktree 同时支持 Linux、macOS 和 Windows,而且它不是把 Linux 逻辑硬搬过去,而是对每个平台都单独回答了同一批问题:

  • Windows:磁盘占用用 NTFS 为每个文件报告的实际分配(整簇,压缩或稀疏文件更少,小到能住进文件记录里的算零),而且它是随目录列出一起来的,所以不比单纯遍历多花成本;硬链接在 NTFS 上也算一次。整盘扫描是「你的用户配置所在的那块盘」,通常是 C:\。回收站走 shell,销毁任何无法回收的东西前会先问。另外它主动拒绝 Windows、Program Files、ProgramData、系统卷信息、恢复分区、Boot,以及页面文件和休眠文件,还有任何装着用户配置的目录(比如 C:\Users)。隐藏文件的定义也按 Windows 来:点开头或带隐藏属性,所以 -H 会把 AppData 藏掉,跟资源管理器一致。
  • macOS:空闲空间采用 df 报的数(Finder 显示的数字更大,因为它把可清除空间也算进去了);APFS 的克隆文件会按完整大小各算一次,所以总数可能超过删掉之后真正释放的量;Time Machine 的本地快照不是文件,不会出现在图里。另外,纯云端的目录(iCloud Drive、Dropbox 等已驱逐到服务器的)不会被打开,所以扫描永远不会触发下载。
  • 主题:在 Omarchy 上跟随你的主题,在 macOS、GNOME 和 KDE 上跟随系统的亮/暗设置。

技术细节与上手

它用 Rust 写成,界面走 GPUI(通过 gpui-omarchy),所以行为和主题都跟 Omarchy 桌面其他部分一致。代码切成两个 crate:disktree-core 负责扫描、树结构、squarified 布局、空闲空间和删除逻辑,不含任何 UI;disktree-app 负责状态机、视图、马赛克绘制和尺度系统。测试不只是单元测试——窗口测试会真正画帧、真正按键,其中一个测试标记一个目录、确认删除、然后检查文件确实没了而邻居还在。

lint 门禁是有意设严的:clippy::all 和 clippy::pedantic 都是 error,每一条例外都必须在 Cargo.toml 里写明理由。

安装:从 latest release 下载对应平台的包(Linux/macOS/Windows 都有,x86_64 与 aarch64 齐全),解压后运行 ./install.sh,或者直接编译:

git clone https://github.com/tobi/disktree
cd disktree
make install

make install 会把三样东西放进 ~/.local(不需要 root):二进制、一个桌面项(所以 disktree 会出现在启动器里,也会出现在文件管理器的「打开方式」中——但它只添加处理器,永远不会把自己变成默认程序),以及一个图标。它需要 Rust 1.97+,以及一个 GPUI 能驱动的 GPU(Vulkan)。

macOS 上还有一个很实用的提醒写在 README 里:未签名未公证的 release 会被 Gatekeeper 拦住,提示「已损坏,无法打开」。其实应用没问题,只是浏览器给它打了隔离标记,清一次就好:

xattr -dr com.apple.quarantine /Applications/disktree.app

想在 macOS 上看到全部内容,需要在「系统设置 → 隐私与安全性」里给它完全磁盘访问权限——否则 macOS 会藏起邮件、信息、Safari 和其他应用的数据以及废纸篓,disktree 只能把它们算作「不可读」,并在顶部如实标出来,而不是瞎猜。

要不要装

如果你在 Omarchy 或者任何 Linux 桌面上,/home 正在吞掉你的 SSD,disktree 是目前为止最舒服的一类解法:看得懂、量得准、删得小心。它唯一的门槛是「面向 Omarchy」这个定位——不过 macOS 和 Windows 版本都在,Wayland/X11 的 GNU/Linux 也能用,只是主题跟随和 Hyprland 规则那些体验是给 Omarchy 特调的(在 Hyprland 上它会被平铺,作者建议加一条浮动规则,窗口类是 disktree)。

如果你只是想找「哪个 node_modules 最肥」这种一次性问题的答案,du | sort 依然更快。但如果你想重新建立对自己磁盘的直觉——尤其是那种「我知道有大东西,但不知道是哪几个」的长期焦虑——把主目录画成一张可以走进去的地图,是相当有效的解法。

项目地址:github.com/tobi/disktree,MIT 许可。

© 版权声明
THE END
喜欢就支持一下吧
点赞10 分享