Rm Is Dangerous!
Short post here but I think it’s worth writing about. I use Linux (Ubuntu) for my primary daily operating system and am in the terminal a lot; while running a certain command that I cannot remember, a directory named ~
(tilde) was created and seeing the mistake I promptly typed rm -rf ~
to delete it.
That was a massive mistake. First mistake was using rm -rf
on an empty directory - that’s what rmdir
is for. My second mistake was a bit more subtle: ~
is an alias for the user’s home directory, in this case, /home/parnell
and typing rm -rf ~
basically said “delete everything recursively in /home/parnell
”.
It wasn’t until two seconds after issuing the command that I realized my grave mistake and sadly, it had already removed everything.
A solution isn’t to just be more careful and diligent but to also realize that there are protections in place for this precise sort of human-prone mistake: the “trashcan”, aliases, and deletion pauses and prompts. The first two solutions go together: I aliased rm
to a small script that mimics its behavior but uses Ubuntu’s trash-put
command to move said directories and files into the trashcan (instead of deleting forever). This is appropriate for the home user, but what about sudo / root?
The final solution is more appropriate for sudo. I have five second pauses and a confirmation prompt whenever I issue an rm command against common or important aliases or globs.
Also - backups, that’s the only reason I was able to bounce back from this mistake!
Below is the alias and script I use to override rm behavior with the trashcan, the script was found on Alin Andrei’s Blog.
alias rm="trash-rm"
#!/bin/bash
# filename: trash-rm
shopt -s extglob
recursive=1
declare -a cmd
((i = 0))
for f in "$@"
do
case "$f" in
(-*([fiIv])r*([fiIv])|-*([fiIv])R*([fiIv]))
tmp="${f//[rR]/}"
if [ -n "$tmp" ]
then
#echo "\$tmp == $tmp"
cmd[$i]="$tmp"
((i++))
fi
recursive=0 ;;
(--recursive) recursive=0 ;;
(*)
if [ $recursive != 0 -a -d "$f" ]
then
echo "skipping directory: $f"
continue
else
cmd[$i]="$f"
((i++))
fi ;;
esac
done
trash-put "${cmd[@]}"