nvrmnd-png/undo

GitHub: nvrmnd-png/undo

一款通过 shell 集成拦截常见文件系统命令并将所有操作记录到 SQLite 的命令行撤销工具,让 mv、rm、cp 等操作均可恢复。

Stars: 42 | Forks: 1

# 撤销 ![许可证](https://img.shields.io/badge/license-GPLv3-blue) ![Rust](https://img.shields.io/badge/rust-2024-orange) ![Shell](https://img.shields.io/badge/shell-zsh%20%7C%20bash%20%7C%20fish-lightgrey) Shell 的文件系统命令是不可逆的:一旦你用 `mv` 覆盖了文件,或者用 `rm` 删除了目录,就没有内置的方法可以恢复。**undo** 会记录所有支持的操作,并可以根据需要撤销它们,而且它从不直接删除任何内容,因此即使是 `rm` 也是可以恢复的。 ![undo 演示:mv 后 undo 恢复了文件,rm -r 后 undo 从回收站恢复了它](https://static.pigsec.cn/wp-content/uploads/repos/cas/03/0396e3fcf3248f81a25928b4c2454d7d747427e566dec54006a6bbd0d1fccac9.gif) 它通过*拦截*命令而不是监视命令来工作:一个小的 shell 集成会将 `mv`、`cp`、`rm`、… 路由到 undo,由后者在 Rust 中自行执行操作,并准确记录如何撤销它。删除的文件会进入 freedesktop.org 回收站,被覆盖的文件会先在那里备份,并且每次回滚在修改任何内容之前都会验证文件的完整性。 ## 支持的命令 `mv` · `cp` · `rm` · `mkdir` · `rmdir` · `chmod` · `chown` · `ln` · `rename` `rm` 和 `rmdir` 会移动到回收站而不是直接删除。覆盖操作(`mv`、`cp`、`ln -f`)会将替换掉的文件存放在回收站中,因此它们是完全可逆的。 `rename` 使用 Perl 的 `s/old/new/` 语法。 ## 安装 ``` git clone https://github.com/nvrmnd-png/undo cd undo ./manager.sh # interactive: build from source or fetch a prebuilt binary ``` `manager.sh install --source` 会使用 `cargo` 构建并安装到 `~/.local/bin`;`--prebuilt` 会下载发布版本的二进制文件并验证其 SHA-256。可以使用 `UNDO_PREFIX` 覆盖安装位置。或者直接使用 cargo: ``` cargo install --path . ``` ### 启用 shell 集成 undo 只会记录通过其包装器执行的命令。在你的 shell 启动文件中添加一行: ``` # ~/.zshrc eval "$(undo init zsh)" # ~/.bashrc eval "$(undo init bash)" # ~/.config/fish/config.fish undo init fish | source ``` 打开一个新的 shell,你日常使用的 `mv`/`cp`/`rm`/… 就变得可撤销了。对于单次调用,可以使用 `command mv …` 或 `\mv …` 来绕过包装器。 ## 用法 | 命令 | 作用 | |---|---| | `undo` | 撤销最近的一次操作 | | `undo redo` | 重新应用最近撤销的操作 | | `undo list` | 显示 undo 和 redo 栈 | | `undo history` | 显示完整日志(`-n N`,`--all`) | | `undo show ` | 详细显示某一条目 | | `undo clear` | 清除日志(绝不触碰回收站) | | `undo tui` | 交互式浏览并执行 undo/redo | | `undo init ` | 打印 shell 集成代码片段 | 全局标志:`--force`(覆盖完整性拒绝;被替换的文件会进入回收站)、`--dry-run`(报告会发生什么)和 `--json` / `--yaml`(稳定的机器输出,`schema: 1`)。 ``` $ undo list Undo stack (newest first): #8 2026-07-14 09:14 applied rm -r build/ #7 2026-07-14 09:12 applied mv report.txt archive/ $ undo history --json | jq '.entries[0].command' "rm" ``` ### 交互式 TUI `undo tui` 会打开一个彩色的浏览器:包含日志条目列表、详细信息面板以及实时完整性徽章。 | 按键 | 操作 | |---|---| | `j` / `k` | 向下 / 向上移动 | | `Tab` | 切换过滤器 | | `v` | 验证所选条目 | | `u` | 撤销所选条目 | | `r` | 重做所选条目 | | `f` | 切换 `--force` | | `?` | 帮助 | | `q` | 退出 | ## 安全性 - **绝不删除任何内容。** `rm`/`rmdir` 使用 freedesktop 回收站;每个破坏性的逆向操作(删除副本、替换覆盖的文件)也都会通过回收站进行。跨设备移动在任何删除之前都会进行经验证的复制。 - **每次回滚前都会检查完整性。** 内容使用 BLAKE3 进行指纹识别(在 64 MiB 以上时为大小 + mtime);自操作以来被修改过的文件将拒绝回滚,除非你传递 `--force`。 - **仅限你的数据。** 日志是私有的(`0600`,已检查所有权),并且会拒绝来自其他用户的条目。 - **在检查期间绝不跟踪符号链接**,并且操作会被锁序列化,在每次变更前立即重新检查。 ### 限制 undo 只能撤销通过其包装器执行的操作。`sudo`、脚本、cron 和 GUI 文件管理器会绕过它们(过期的日志会被验证机制捕获,而不是盲目地重放)。复制目录树内的 ACL、xattrs 和硬链接拓扑不会被保留。非 UTF-8 路径会回退到真实命令。清除日志不会清空回收站。完整列表请参见 `man undo`。 ## 工作原理 每个操作都存储在特定用户的 SQLite 日志中(`$XDG_DATA_HOME/undo`),包含其命令行、工作目录、每个受影响节点的操作前/后状态,以及确切的逆向操作。`undo`/`redo` 会将其作为栈来处理;新的操作会像编辑器一样清除 redo 栈。回滚过程中的部分失败会补偿回一致的状态,并且因为所有被替换的内容都存在于回收站中,即使在最坏的情况下也不会丢失任何内容。 ## 开发 ``` cargo test # 150+ unit and integration tests cargo clippy --all-targets cargo fmt --check ``` ## 支持 如果 undo 帮你避免了一次糟糕的 `rm`,可以考虑赞助一下: | 资产 | 地址 | |---|---| | BTC | `bc1qmgnz54x4epaeuvz558z4d7n3a3dqk3vldsgcnt` | | XMR | `43eLK3JjmkDiWAuP9b5N8sahtzQQByaVSEPbZvVTctXAYJ1cHGXbVL3f8PSREnmnSsY4rMkhx14UA8vxc5sfz4ZhDfxKkg5` | | ETH | `0x8CF98DeF5d716E10697E5905caff34b405dcd4fF` | | SOL | `DFwWy5EMB5QRd1FTV81ft5WYyH6uHecRvPsXkLNRyh1s` | ## 许可证 GPLv3 © 2026 nvrmnd。请参见 [LICENSE](LICENSE)。
标签:Rust, Shell扩展, 可视化界面, 数据恢复, 文件管理, 系统运维, 网络流量审计, 通知系统