用 trash-cli 替代 rm 是最稳妥的选择:它遵循 freedesktop 规范,与 gnome/kde 回收站互通,支持恢复原路径、安全清空及跨文件系统处理,且不破坏脚本兼容性。

用 trash-cli 替代 rm 是最稳妥的选择
直接改写 rm 别名看似简单,但会破坏脚本兼容性、绕过权限检查,且无法处理硬链接、符号链接或跨文件系统移动等边界情况。trash-cli 是目前最成熟、被主流发行版仓库收录的命令行回收站工具,它严格遵循 FreeDesktop.org 的 Trash 规范,和 GNOME/KDE 的图形回收站共用同一套底层路径(~/.local/share/Trash),恢复、清空、查看行为完全一致。
安装后不用动 rm,而是养成用 trash 的习惯:
-
trash file.txt:把单个文件移入回收站(支持通配符,如trash *.log) -
trash list:显示文件名、原始路径、删除时间、大小,比ls ~/.local/share/Trash/files更直观 -
trash restore:交互式选择恢复哪个文件,自动还原到原路径(即使原目录已不存在,也会提示) -
trash empty:清空全部;加数字如trash empty 7只清 7 天前的
注意:trash 不接受 -r 或 -f 参数——它天生就不支持强制递归删除,这反而是安全设计。
别名改写 rm 有明确限制,慎用
如果你坚持让 rm 命令走回收站,必须清楚这些硬伤:
- 不能覆盖
rm -rf /path这类带选项的调用,除非你写完整函数封装,但会丢失 POSIX 兼容性 -
mv -t ~/.trash "$@"在遇到同名文件时会静默覆盖,没有冲突提示 - 不记录原始路径信息,恢复时只能靠文件名猜,
trash-restore那种“还原到原位置”能力完全缺失 - 如果
~/.trash和源文件不在同一文件系统,mv实际是 copy + unlink,可能触发磁盘满错误且不报错
若仍要尝试,只建议在交互式 shell 中使用,且必须加上时间戳隔离:
function rm() {
mkdir -p ~/.trash/$(date +%Y%m%d_%H%M%S)
mv -t ~/.trash/$(date +%Y%m%d_%H%M%S) "$@" 2>/dev/null || command rm "$@"
}
这样至少避免覆盖,也方便手动翻找。但请勿在脚本中启用此函数。
GNOME/KDE 桌面下,命令行和图形回收站天然互通
只要你没动过默认配置,GNOME 的 nautilus、KDE 的 dolphin 删除文件时,实际都写入 ~/.local/share/Trash/files/ 和对应 info/ 元数据。这意味着:
- 你在文件管理器里删的文件,
trash list能立刻看到 - 你在终端用
trash删的,桌面右下角回收站图标会实时更新计数 - 恢复操作双向有效:图形界面拖出来,或终端
trash restore,结果一致
唯一例外是 gvfs-trash,它是 GNOME 专用的旧接口,现在已被 trash-cli 全面兼容替代,无需单独安装或调用。
清空与清理不能只靠 rm -rf
直接 rm -rf ~/.local/share/Trash/files/* 看似快,但会留下 info/ 目录里的孤立元数据,下次 trash list 可能报错或显示乱码。正确做法只有两个:
- 用
trash empty:它会同步清理files/和info/,并校验完整性 - 用
find定时清理时,必须成对操作:find ~/.local/share/Trash/files -type f -mtime +30 -delete -exec dirname {} \; -exec basename {} \; | while read d b; do rm -f "$d/../info/${b}.trashinfo"; done
更推荐前者。定时任务也应调用 trash empty 30,而不是手写 find —— 工具本身已内置防误删逻辑,比如跳过正在被其他进程打开的文件。
真正容易被忽略的是:所有回收站方案都对 rm -rf 无效。它永远绕过任何上层封装,直击文件系统。所以最核心的安全习惯不是设回收站,而是执行前先 echo 出目标路径,或用 ls 确认范围——回收站只是最后一道缓冲,不是保险箱。











