A safer rm
I spend a lot of time in the terminal, which means deleting files and
rm isn't fussy about what it deletes and
doesn't believe in second chances. For interactive use, I think we can do a bit
better. In this article, I'll first discuss some safer alternatives to
then offer my current preferred solution.
One of the older (though still maintained!) efforts to improve the safety of
rm is safe-rm, which is a simple wrapper
rm that refuses to delete a list of protected directories. By default
rm will refuse to remove the root of the filesystem,
/, but that's it. In
safe-rm refuses to remove a list of important system directories,
/usr. Additional directories can be protected by listing
them in a configuration file.
safe-rm was originally a Perl script but has
recently been rewritten in Rust, and is meant to be a drop-in replacement for
The key feature of the subsequent alternatives is that files are moved to some trash directory instead of being immediately deleted, much like typical desktop GUI trash programs. This allows files deleted by mistake to be restored until the trash is permanently deleted later.
One example is shell-safe-rm,
which is a bash script that aims to be an almost-complete drop-in replacement
rm, except that it moves files to the directory
~/.Trash. The tool does
not provide a built-in mechanism for restoring or emptying the trash, leaving
this for the user to do manually.
Another example is rip, which is written in
rip is intended to be an intuitive and ergonomic alternative to
rather than a drop-in replacement. In particular,
rip doesn't bother with
-r or other flag to remove directories. Like
shell-safe-rm, it moves
deleted files to a particular directory. By default,
rip uses a directory in
/tmp, so that the deleted files are automatically cleaned up when the
computer reboots. I'm a little hesitant about this, in case my computer crashes
or otherwise reboots before I realize a file was removed by mistake; I want a
more predictable process for permanent deletion. Luckily,
rip allows the
destination for deleted files to be easily changed through environment
variables or a command line argument.
Finally, a rather attractive prospect is to follow the same specification as
common Unix desktop GUI trash programs, the XDG trash
popular CLI tool that implements this spec is the Python tool
scripts for all of the utilities expected from a trash program: move files to
trash, inspect them, restore them, or delete them permanently.
My preferred alternative
Ultimately, I want a tool with the following features:
- Move files to a trash directory rather than immediately deleting
permanently. This is typical of GUI trash programs and a main feature of
- Confirmation before deleting multiple items (to avoid, say, an incorrect
glob). This is actually present in plain
-iflag prompts before removing each and every file;
-Iprompts once before removing directories or more than three files.
- Refuse to delete a protected list of directories, like
- Files are automatically permanently deleted after having been in the trash
I played around with my own implementation of (1) for a while, but eventually
decided to just wrap
trash-cli to get (1) and the rest of the XDG trash spec
for free. My wrapper just adds features (2)
and (3), both of which are quite simple to implement, on top of the
For feature (4), I initially had each call to my wrapper check for files older
than 7 days and delete them, which can cause a noticeable delay if there
is a lot to delete. A better solution is to set up a cron job to regularly
empty the trash automatically. One way to do this is to use the
trash-cli and a crontab entry like
@daily /path/to/trash-empty 30
which runs a daily job to remove files that have been in the trash for at least 30 days.
I'll also mention autotrash, which is a dedicated tool for automatically emptying the trash can. It can set up a systemd service to do so, or can be added as a cron job similar to the one above.
I discussed four safer versions of
After hacking on my own toy version for a little while, I ended up wrapping
trash-cli and using a cron job to automatically remove old trash. If you have
an alternative (better?) solution to removing files in the CLI, I'd be happy to
hear about it by email or