UNIX、Linux 下的 rm 删除文件后难以恢复,很多人会设置别名 rm=‘rm -i’,但删除时的提示很烦人,而且会被 rm -rf 的 -f 覆盖,不会提示。于是,很多人会写替代版的 rm,思路很简单,把 rm 变成 mv 语义,按日期放入某个 Trash 目录,很多年前我也写过一段穷人的回收站:

## in ~/.bashrc

safe_rm () {
    local d t f s

    if [ -z "$PS1" ]; then
        /bin/rm "$@"
    else
        d="${TRASH_DIR:=$HOME/.__trash}/`date +%Y%m-%W`"
        t="`date +%F_%H-%M-%S`"

        mkdir -p "$d" || return

        for f do
            [ -e "$f" ] || {
                echo "Not found: $f" >&2
                continue
            }

            perl -MCwd -e 'index(Cwd::abs_path($ARGV[0]), $ARGV[1]) == 0 ? exit(1) : exit(0)' \
                    "$f" "${TRASH_DIR:-$HOME/.__trash}" || {
                echo "Please use /bin/rm or \rm to delete files in trash." >&2
                continue
            }

            s=$d/`basename "$f"`-$t-$RANDOM
            # Loudly, train users to be careful without this message.
            echo "Move $f to $s ..."
            /bin/mv "$f" "$s" || break
        done

        echo -e "[$? $t `whoami` `pwd`] $@\n" >> "$d/00rmlog.txt"
    fi
}

alias rm=safe_rm

今天刚注意到 FreeDesktop 定义过回收站规范,有两个跨平台的命令实现:

  1. trash-cli

使用 Python 编写,被 Debian 收录了,它提供如下命令:

  • trash: 移动文件到回收站(默认在 ~/.local/share/Trash),并记录原路径和删除时间;
  • trash-empty:清空回收站,支持清空多少天以前的文件;
  • trash-list:列出被删文件的原路径和删除时间;
  • trash-put: 同 trash 命令;
  • trash-restore:恢复文件,存在多个被删的同名文件时会询问恢复哪个;
  • trash-rm: 删除回收站中的文件,注意这个命令不询问,有同名文件时会全部删除;

这个工具缺一个 UI 去查看被删文件的内容,不过也问题不大,进 ~/.local/share/Trash 查看即可。

  1. gtrash

这个工具比 trash-cli 功能更多,UI 更友好,使用 Go 编写,提供了 gtrash 命令,这个命令有如下子命令:

  • gtrash find: 列举回收站中的文件,可以按名字和时间过滤,并能顺带清除或恢复;
  • gtrash prune:按日期和大小清除回收站中的文件;
  • gtrash putrm 的替代
  • gtrash restore:恢复文件,这个命令会展示一个 TUI 界面,能预览文件内容,非常好用;
  • gtrash restore-group:按秒级范围的删除时间成组的恢复文件;
  • gtrash rm:删除回收站中的文件,会询问,但不能选择删除同名文件中的某一个;
  • `gtrash summary: 显示回收站里有几个文件,占据多少磁盘空间;

虽然两个工具的文档都不建议用alias rm='trash-put' 而是建议设个其它的别名比如 del,但我还是选择直接用 alias rm='...',已经太习惯这个命令了。