定位:Rust 编写的跨平台磁盘空间分析、可视化、清理工具。 双端:ratatui TUI + egui 桌面 GUI。 核心目标:WizTree 级扫描速度、Cleaner 级清理体验、扫描时 UI 不卡。|作者个人站:https://softwarescience.top/projects/spacelens
当前访问频次受限,请登录后继续访问
SpaceLens / 盘镜
作者个人站:https://softwarescience.top/ · 本项目主页:https://softwarescience.top/projects/spacelens(版本、截图与下载都在那儿)
Rust 编写的跨平台磁盘空间分析、可视化与清理工具。终端界面(ratatui TUI)、桌面界面(egui GUI)与命令行(clap CLI)共用同一套扫描引擎与不可变快照。
扫描走快照、删除走队列、UI 永远只读不可变快照,所以扫描时界面不会卡。
1. 这是什么
盘镜回答三个问题:
- 空间去哪了:按目录逐层下钻,看大小、占比、修改时间;矩形树图一眼看出「谁最大」。
- 什么可以删:重复文件检测、大文件视图、按类型统计、规则引擎给出的清理建议(带风险等级)。
- 删了会不会出事:删除前先出计划(多少项、多少 GB、哪些被拦截),默认进回收站,永久删除必须显式确认。
三种入口,一套内核:
| 入口 | 命令 | 适合 |
|---|---|---|
| 终端界面 | spacelens tui [路径] |
服务器、SSH、不想离开终端 |
| 桌面界面 | spacelens gui [路径] |
日常清理、看矩形树图 |
| 命令行 | spacelens scan/dup/clean/... |
脚本、批处理、CI |
2. 特性
| 功能 | 状态 | 说明 |
|---|---|---|
| 并行目录遍历扫描(jwalk + rayon) | ✅ | 跨平台默认路径,进度实时上报,可取消 |
| Windows NTFS MFT 快速扫描 | ✅ 代码完整 / ⚠️ 需管理员 | 直接解析 $MFT,allocated 为精确分配大小;非管理员自动降级并在界面标注原因 |
| 不可变快照 + 无锁读取 | ✅ | 扫描线程与 UI 完全解耦,ArcSwap 发布 |
| 文件夹占用排行 / 大文件视图 | ✅ | 按大小、名称、占用、时间、类型、子项数排序 |
| 矩形树图(squarified treemap) | ✅ | TUI 与 GUI 共用同一份布局算法 |
| 过滤表达式 | ✅ | size>1G ext:mp4 older:30d dir 名称关键词 |
| 重复文件检测 | ✅ | 大小分组 → 首尾 64 KiB 快速哈希 → 全量 SHA-256 三级过滤 |
| 按类型统计 | ✅ | 视频/图片/音频/压缩包/程序/源代码/文档/临时… |
| 清理规则引擎 | ✅ | TOML 规则 + glob 匹配 + 风险等级(低/中/高);内置「开发缓存」「系统临时文件」「大视频」等规则 |
| 删除计划与安全拦截 | ✅ | 去重、受保护路径、卷根/扫描根拦截、dry-run、永久删除二次确认 |
| 回收站删除 | ✅ | 默认方式,走系统回收站(Windows 为 Shell IFileOperation) |
| 快照保存 / 载入 / 对比 | ✅ | redb 持久化,对比报告含新增/删除/增长/缩小与净变化 |
| 导出 CSV / JSON | ✅ | 命令行与界面都可导出 |
| 卷容量总览 | ✅ | 各盘已用/可用/使用率、介质类型 |
| 中文排版适配 | ✅ | 三端按显示宽度对齐(中文算 2 列),内置字体回退,视觉模型核验脚本 |
| 增量扫描 | ✅ | 只重扫变更子树(目录 mtime 判定),不可增量时自动退化为全量(scan --incremental) |
| 文件系统监视 | ✅ | 目录变动即时增量更新(TUI/GUI 扫描完成后自动开启) |
| 远程扫描(SSH) | ✅ | 远端跑同款扫描器,二进制快照流回本地(scan --remote user@host:/path) |
| 回收站「撤销」 | ✅ | 按 $I/$R/.trashinfo 元数据映射还原(spacelens undo;TUI 快捷键 U) |
| 插件式规则(脚本动作) | ✅ | 规则可挂外部命令:预演 → 显式确认 → 超时强杀,不经 shell |
3. 快速开始
3.1 构建
cargo build --release
产物:target/release/spacelens.exe(Windows)/ target/release/spacelens。
3.2 三种入口
spacelens tui D:\ # 终端界面
spacelens gui D:\ # 桌面界面
spacelens scan D:\ --top 30 # 命令行分析
3.3 想先拿假数据试试
python tools/make_demo_tree.py # 生成 .spacelens-dev/demo(含中文目录名、缓存目录、重复文件)
spacelens scan .spacelens-dev/demo --top 20
spacelens dup .spacelens-dev/demo --min-size 100K
spacelens tui .spacelens-dev/demo
WizTree 之外的真实场景:直接 spacelens scan D:\(管理员身份可走 NTFS MFT 快速路径)。
4. 命令行用法
# 扫描
spacelens scan D:\ --top 30 --top-files 20 # 目录排行 + 全树最大文件
spacelens scan D:\ --filter "ext:mp4 size>1G" # 过滤表达式
spacelens scan D:\ --exclude "**/node_modules" --json
spacelens scan D:\ --save 首次快照 # 扫描并保存快照
spacelens scan D:\ --no-mft --threads 8 # 关闭 MFT、限制线程
# 重复文件
spacelens dup D:\ --min-size 10M --quick
# 清理(默认只预演,绝不动磁盘)
spacelens clean D:\下载 --filter "ext:tmp" # 预演
spacelens clean D:\下载 --filter "ext:tmp" --trash --yes # 进回收站
spacelens clean . --rule "开发缓存" --permanent --yes # 按规则永久删除(会二次确认)
spacelens clean . --rule "导出清理" --run-scripts --yes # 执行脚本动作规则(高风险:--run-scripts + --yes 双开关)
# 撤销还原(默认只预演;--yes 才动磁盘)
spacelens undo # 预演最近一条可撤销删除
spacelens undo --last 3 # 预演最近 3 条
spacelens undo --id 5 --yes # 还原删除日志 #5
# 增量扫描(只扫变更目录)与远程扫描(远端需装 SpaceLens)
spacelens scan D:\ --incremental
spacelens scan --remote user@server:/var/data --top 20
# 快照
spacelens snapshot save 周一 D:\
spacelens snapshot list
spacelens snapshot compare 1 2 --top 30
spacelens snapshot export 2 --format csv --out today.csv
# 其它
spacelens volumes # 各盘容量
spacelens rules list # 当前生效规则
spacelens rules init # 导出规则模板
spacelens config init && spacelens config path
spacelens export D:\ --format json --out full.json --files-only
全局开关:--config <文件>、--cache <文件>、--json、--no-cache、--quiet。
4.1 退出码
| 码 | 含义 |
|---|---|
| 0 | 成功 |
| 1 | 出错(扫描失败、参数非法、计划被拒绝等),错误信息以 错误: 开头 |
5. 界面
5.1 TUI 按键
| 键 | 功能 |
|---|---|
Enter |
进入目录 / 查看 |
Backspace u |
返回上级 |
↑ ↓ PgUp PgDn Home End |
移动游标 |
Space |
勾选 / 取消 |
a / c |
全选 / 清空选择 |
s |
排序菜单(键 + 方向) |
t |
切换视图:列表 / 矩形树图 / 大文件 / 重复文件 / 类型统计 / 清理建议 |
/ |
过滤表达式输入 |
: |
命令模式(:scan <路径>、:filter size>1G、:delete selected --trash、:dup、:snapshot save <名称>) |
d |
删除到回收站(需确认) |
D |
永久删除(需输入 yes) |
U |
撤销最近一次删除(从回收站还原) |
r |
重新扫描 |
? |
帮助 |
Esc |
关闭浮层 / 取消扫描 |
q / Ctrl+C |
退出 |
5.2 GUI 布局
┌──────────────────────────────────────────────────────────────┐
│ 工具栏:路径输入 · 扫描 · 取消 · 视图切换 · 删除 · 规则 · 快照 │
├────────────┬─────────────────────────────────┬───────────────┤
│ 卷与目录树 │ 列表 / 矩形树图 / 大文件 / │ 详情与操作 │
│ │ 重复文件 / 类型统计 / 清理建议 │ │
├────────────┴─────────────────────────────────┴───────────────┤
│ 状态栏:进度 · 速度 · 当前路径 · 已选 N 项 · 可释放 X GiB │
└──────────────────────────────────────────────────────────────┘
- 中文字体自动从系统加载(微软雅黑等);找不到时界面顶部会显示红色提示,而不是渲染成方块。
- 长路径在单元格内截断(不换行),行高固定,中文不会被裁掉。
- 删除确认弹窗会列出计划摘要与被拦截项,永久删除需要额外勾选。
6. 配置与规则
配置文件默认位于 %APPDATA%\SpaceLens\config.toml(其他平台 $XDG_CONFIG_HOME/spacelens/config.toml)。
[scan]
follow_links = false # 是否跟随符号链接
include_hidden = true # 是否统计隐藏文件
prefer_mft = true # Windows 优先尝试 NTFS MFT(需要管理员)
exclusions = ["**/node_modules", "**/.git"]
[delete]
default_mode = "trash" # trash | permanent
require_confirmation = true
protected_paths = ["C:\\Windows", "C:\\Program Files"] # 这些路径及其子树禁止删除
[rules]
enabled = true
path = "C:\\Users\\me\\AppData\\Roaming\\SpaceLens\\rules.toml"
[ui]
language = "zh-CN"
page_size = 200
规则文件(spacelens rules init 生成模板):
[[rules]]
name = "开发缓存"
match = ["**/node_modules", "**/target", "**/.venv", "**/__pycache__"]
action = "trash"
risk = "low"
[[rules]]
name = "大视频"
match_ext = ["mp4", "mkv", "mov"]
min_size = "1GB"
action = "mark"
risk = "medium"
# 脚本动作:命中后执行外部命令(高风险,需 --run-scripts + --yes 双开关才执行)
# 占位符:{path} {name} {size} {ext};命令与参数逐段传递,不经 shell
[[rules]]
name = "导出清理"
match = ["**/导出/*.tmp"]
action = "script"
[rules.script]
command = "python"
args = ["cleanup.py", "{path}", "{size}"]
[[rules]]
name = "冷日志"
match_ext = ["log"]
older_than_days = 30
action = "trash"
risk = "low"
action:trash(建议回收站)/permanent(建议永久删除)/ignore(永不建议)/mark(只标记)。risk:low/medium/high,界面按等级着色,高风险默认不勾选。- 单位语义:
KB = 1000、KiB = 1024(G/GB与GiB同理)。
7. 架构
前端 ratatui TUI ─┐
egui GUI ─┼─ Command(下发) / CoreEvent(上报)
clap CLI ─┘ │
▼
spacelens-core 引擎
┌──────────────────────────┼──────────────────────────┐
扫描调度线程 工作线程池 快照发布
(命令总线) 扫描 / 删除 / 哈希 ArcSwap<Snapshot>
│ │ │
spacelens-mft spacelens-delete spacelens-cache
(NTFS $MFT) (回收站 / 永久) (redb 快照与日志)
│
spacelens-rules(TOML 规则)
| crate | 职责 |
|---|---|
spacelens-core |
数据模型(Arena + NodeId)、扫描、删除、重复检测、快照对比、格式化、引擎 |
spacelens-rules |
TOML 规则解析与匹配、parse_size |
spacelens-cache |
redb 持久化:快照、删除日志、KV |
spacelens-mft |
NTFS $MFT 解析(BPB、FILE 记录、USA 修复、属性遍历) |
spacelens-ui-common |
双端共享 UI 状态:过滤表达式、排序、选择、treemap 布局 |
spacelens-tui |
ratatui 终端界面 |
spacelens-gui |
egui 桌面界面(glow 后端) |
spacelens-cli |
可执行文件 spacelens |
7.1 四条不变式
- UI 线程不做 IO:扫描/删除/哈希都在工作线程,UI 只读快照与事件。
- 快照发布后只读:修改 = 克隆出新快照再发布,读侧无锁。
- 危险操作先成计划:删除必经
plan()(去重 + 拦截 + 确认位)再execute()。 - 目录大小恒为子树汇总:由引擎统一计算,保证一致且可重算。
7.2 数据结构
type NodeId = u32; // Arena 下标,替代指针
struct FileNode { parent, children, name: Box<str>, kind, size, allocated, mtime }
struct Snapshot { nodes: Vec<FileNode>, root, root_path, source, totals, version, ... }
百万级节点的内存占用主要是 Vec<FileNode>(每节点约 72 字节)加上名字字符串,节点不存完整路径,路径按需拼装。快照用自定义二进制格式(magic SLSN + 版本 + 校验),解码后会重算统计值与记录值比对,损坏数据直接报错而不是静默出错。
8. 性能与验证
本机实测(Ryzen 9 9900X / 24 线程 / Windows 11 26200 / release 构建):
| 场景 | 结果 | 命令 |
|---|---|---|
C:\Windows\System32(24,565 文件 / 1,562 目录 / 10.76 GiB) |
2.5 s(≈ 10k 项/秒,冷缓存首轮 3.4 s) | cargo run --release -p spacelens-core --example bench_scan -- "C:\Windows\System32" |
本仓库 target(12,687 文件 / 1,122 目录) |
1.0 s(≈ 13k 项/秒) | 同上 |
| 小目录(41 项) | 6 ms | 同上 |
说明:
- 并行遍历路径在 Windows 上每个条目需要一次元数据调用,吞吐量约 10–14k 项/秒;百万文件约 70–100 s,与设计目标(< 60 s)同量级。
- NTFS MFT 快速路径目标为「百万文件 < 10 s」:解析器有合成镜像单测覆盖,但需要管理员权限,本机(非管理员)只验证了自动降级路径。
- Windows 并行遍历的
allocated按 4 KiB 簇向上取整估算(Metadata不提供分配大小);MFT 路径给出精确值。 allocated在 macOS/Linux 上由st_blocks × 512得出,精确。
8.1 测试
cargo test # 全量:246 个测试(单元 + 端到端 + 无头渲染),全绿
cargo test -p spacelens-core --test e2e # 真实文件系统端到端
cargo clippy --workspace --all-targets # 0 warning
各 crate 的测试分布:
| crate | 覆盖 |
|---|---|
spacelens-core |
40 单元 + 11 真实文件系统端到端 |
spacelens-mft |
34(合成 NTFS 镜像、USA 修复、DOS 短名、扩展记录、BAAD 记录) |
spacelens-rules |
38 + 2 外部 API 契约 |
spacelens-cache |
15 + 2 外部 API 契约 |
spacelens-ui-common |
25(CJK 宽度、过滤表达式、treemap 几何、选择去重) |
spacelens-tui |
30 单元 + 7 无头整帧渲染 |
spacelens-gui |
20 单元 + 2 二进制入口 |
spacelens-cli |
4 单元 + 12 真实二进制端到端 |
覆盖要点:
- 核心端到端:在临时目录树(含中文目录名/文件名)上扫描,断言文件数、目录数、总字节数、路径重建、排序、排除规则、取消、MFT 降级、删除计划与执行、受保护路径拦截、快照存/取/对比、重复文件、异步事件顺序。
- CLI 端到端:运行真实二进制,断言中文表头、JSON 字段、CSV 行数与内容、预演不落盘、永久删除需要
--yes、无过滤条件时拒绝清理、快照全流程。 - TUI:用 ratatui
TestBackend无头渲染整帧(120×40 / 60×24 / 44×14 / 20×5 等尺寸、6 种视图),断言「每行显示宽度不超过帧宽」「不出现替换字符」以及关键中文标签存在。 - GUI:字体探测(真实系统字体签名)、表格行模型、treemap 命中测试、删除确认门的勾选要求。
- 解析器:NTFS 合成镜像逐字段断言,且全部无需管理员权限。
8.2 截图核验(已执行)
TUI 与 GUI 都在真实窗口里跑过并逐像素确认:
| 检查项 | 结果 |
|---|---|
| 中文显示 | 正常,无方块/乱码(GUI 自动加载系统字体:msyh.ttc 等) |
| 列对齐 | 列表的 名称/大小/占用/修改时间/类型 按显示宽度对齐(中文算 2 列) |
| 截断 | 无越界、无压住相邻元素;长路径在面板内换行且不破坏边框 |
| 发现的真实缺陷 | GUI「修改时间」列宽 116 px 放不下 2026-09-23 23:28 被截断 → 已改为 150 px |
自动化工具(tools/ui_verify.py)支持按窗口标题截图(PrintWindow,被遮挡也能抓;GL 窗口抓到空白时自动回退整屏裁剪)、注入鼠标点击、以及把截图交给本地视觉模型逐条检查排版清单。核验截图存在 screenshots/(未纳入版本控制)。
9. 安全说明
磁盘清理工具最怕的就是「手一抖删错」。盘镜的策略:
- 默认不删:
clean不带--yes只预演;TUI/GUI 的删除也要确认。 - 默认回收站:永久删除需要显式
--permanent且--yes(界面上还要额外勾选)。 - 受保护路径:
C:\Windows、Program Files、ProgramData、~/.ssh、~/.gnupg等及其子树禁止删除;卷根与扫描根本身禁止删除。路径比较对大小写、正反斜杠、\\?\扩展前缀免疫,无法用不同写法绕过。 - 去重:勾了目录又勾它里面的文件时,只删目录一次,可释放空间不重复计算。
- 可审计:删除日志(路径、大小、方式、成功与否)写入
cache.redb。 - 无过滤不清理:
clean未指定--filter/--rule时直接拒绝执行,避免误删整个目录。
10. 路线图
11. 开发
cargo test # 全量测试
cargo run -p spacelens-cli -- scan . --top 10
cargo run --release -p spacelens-core --example bench_scan -- D:\ 3
工程约定、依赖踩坑记录、中文排版规范见 AGENTS.md。
12. 变更记录
未发布
- 修复(实机验证发现):NTFS
$MFT多 run(物理不连续)时按线性偏移读取会把后段记录读成别的数据,导致条目大面积缺失、「MFT 中不存在路径」后降级 Walk。现按记录 0$DATA的 mapping pairs(runlist)把流内偏移映射到卷上偏移,并补碎片化/短读回归测试与真实卷实机测试(tests/real_volume.rs)。 - 新增增量扫描、文件系统监视、远程扫描(SSH)、回收站撤销、插件式规则(脚本动作),对应 CLI 子命令与 TUI 快捷键见上文。
- 界面修复:底部扫描进度不再与右下角「已选」摘要重叠(左右分栏、长路径截断);「取消」现在会一并停止扫描与自动更新,取消后界面立即恢复可扫描状态(此前会卡在「扫描中」)。
- 界面增强:表格与目录树增加「占比」(相对当前目录);矩形树图改为 wintree 式热点色阶(冷→热五档 + 左下角图例),格子标签带占比;目录树的展开三角与「进入目录」动作分离(点三角只展开/收起,点目录名才进入)。
v0.1.0
- 首个可用版本:核心引擎、并行扫描、NTFS MFT 解析、TUI、GUI、CLI、规则引擎、快照缓存、重复文件检测、删除计划与安全拦截。
13. 许可
MIT,见 LICENSE。
关于
这个项目由 CodeLife Leon 独立开发与维护。更多项目、各项目发版信息、赞赏与联系方式都在个人站:
- 个人站:https://softwarescience.top/
- 本项目主页:https://softwarescience.top/projects/spacelens
- 下载与发版:https://softwarescience.top/releases/spacelens
- 赞赏支持:https://softwarescience.top/sponsor(自愿,不影响任何版本的发布)
问题反馈与需求建议:优先在仓库提 Issue,也可以邮件 virgil_lgp@163.com。
项目介绍
定位:Rust 编写的跨平台磁盘空间分析、可视化、清理工具。 双端:ratatui TUI + egui 桌面 GUI。 核心目标:WizTree 级扫描速度、Cleaner 级清理体验、扫描时 UI 不卡。|作者个人站:https://softwarescience.top/projects/spacelens
https://softwarescience.top/projects/spacelens定制我的领域