rm -rf overdose
When a tiny error makes you lose time and money
The rm
command on Unix and the -rf
flags are like bread and butter. At least for me, it's hard to imagine running the rm
command without those flags. As a matter of fact, it became like an instinct and almost as if the command was always rm -rf
.
If you know what you are doing, you can be safe running the full command like that all the time, but I should know myself better and recognize that it is going to be way better for me to think twice before hitting the Enter key. Let me tell you about what happened to me a few weeks ago when I lost a whole day of progress on a project running on a Google Compute Cloud instance for which I was paying 1.5 USD an hour. Essentially, running an rm -rf
command without giving it second thoughts made me lose around 15 USD. Which is not a lot of money compared to what happened to Pixar for running this exact same command a few years ago.
An introduction to rm
The way I usually used rm -rf
is extremely simple:
rm -rf directory_to_delete/
I just specified the path to the directory I wanted to remove recursively and I'm done! Great đ¯đ¯đ¯. To gain more context let's break the command step by step:
rm
: As its own manual (for the BSD version) says:
The rm utility attempts to remove the non-directory type files specified on the command line. If the permissions of the file do not permit writing, and the standard input device is a terminal, the user is prompted (on the standard error output) for confirmation.
So there you go, the basic command to remove files in Unix.
-
-r
: Recursively remove directories. Remember howrm
attempts to remove non-directory type files? Well, with this flag it will remove directories (and their contents). -
-f
: Never prompt for confirmation, even if the file that it's attempting to delete do not permit writing.
Don't try this at /home
Let's set up a test environment to show you the silly mistake I made the other day. I will spin up an Ubuntu container using Docker, but if you like you could use any Virtual Machine, Cloud Instance, a disk partition of your old laptop with a Linux distro you use for experiments, anything you like. Just avoid playing with rm
on your main machine, especially near your important files, please đ.
I'll start by running an interactive Ubuntu session with docker and creating a basic file structure:
$ docker run -it --rm ubuntu
root@ubuntu:/# cd home/
root@ubuntu:/home# mkdir my-files
root@ubuntu:/home# cd my-files
root@ubuntu:/home/my-files# mkdir pictures
root@ubuntu:/home/my-files# mkdir music
root@ubuntu:/home/my-files# mkdir code
root@ubuntu:/home/my-files# mkdir docs
root@ubuntu:/home/my-files# cd docs
root@ubuntu:/home/my-files/docs# mkdir pdfs
root@ubuntu:/home/my-files/docs# mkdir business
root@ubuntu:/home/my-files/docs# mkdir tmp
OK, so far we are just creating a bunch of directories. The structure is as follows:
|- my-files
| |- pictures
| |- music
| |- code
| |- docs
| | |- pdfs
| | |- business
| | |- tmp
Now imagine that we would like to get rid of the tmp
directory under the /docs
directory (funnily enough, this was actually what I was trying to do!), we can achieve this by doing:
rm -rf /home/my-files/docs/tmp
We could also do it using relative paths, so for instance, if our current working directory is /home/my-files/docs
we could do instead rm -rf tmp/
.
Now, here comes what I did wrong the time I was trying to delete my tmp
directory:
rm -rf /home/my-files/docs/tmp\
Can you spot the difference with the original command? It's just a character! Right before I pressed the Enter key I accidentally pressed the key right above it in my Macbook keyboard, the backslash character \
. What's so special about the backslash character on a bash command? It escapes the next character to avoid it to be interpreted by the shell. So in my case when I pressed the Enter key my rm
command didn't run yet.
Hmm. That could be potentially good, right? Actually, yes! That little mistake can give you one more chance to review that the line you've written is correct and if you spot any typo, disregard it before doing any damage đ. The problem is that, if you happen to not be paying enough attention (which was definitely my case), you could end up not realizing that your rm
command didn't run yet and move to the next command as if everything went smoothly. And what happens if the next command you run is a cd
(change directory)? đ¤ let's go ahead and try it:
root@ubuntu:/# rm -rf /home/my-files/docs/tmp\
> cd /home/my-files
Run it and... all of our folders are gone đą
Wh...what happened?
Remember how we said that the \
made the shell ignore the next character? Well... That means that our previous command is equivalent to this:
rm -rf /home/my-files/docs/tmpcd /home/my-files
I didn't know that rm
could be used to remove multiple directories at the same time, but it turns out it is possible. So here we are trying to delete two directories: /home/my-files/docs/tmpcd
(which doesn't exist since the cd
suffix shouldn't be there) and... /home/my-files
đąđąđąđą. So, even if I originally was extremely confident about running rm -rf /home/my-files/docs/tmp
since of course I wanted to remove that directory and thus the -f
flag wouldn't be a problem, I wasn't aware that the shell didn't run the command yet, so the cd /home/my-files
of the next line wasn't interpreted as a change directory command.
What can I do to prevent this?
First of all, have frequent backups and test recover from them from time to time. If possible, make sure to have more than one physical copy of your files and also store what you can in a secure cloud. Mistakes, accidents, and disk issues happen and you never know when.
If your platform is running the GNU version of rm you can use the -I
(uppercase i) flag instead of -f
and you will receive a prompt before the actual execution of the destructive action (unless you are trying to remove less than 4 files and not recursively). It's similar to -i
(lowercase i) but far less annoying and is perfect for the situation described in this post.
Let's see it in action:
root@ubuntu:/# rm -rI /home/my-files/docs/tmp\
> cd /home/my-files
rm: remove 2 arguments recursively?
If we were using the -I
flag, we would be surprised to see the rm
confirmation prompt after what we thought was a cd
command. It gives us much higher chances of catching this kind of errors and in general, it gives us one more chance of thinking about what we are about to do.
BUT... it's not available by default on macOS âšī¸. The thing is that the rm
implementation found on macOS is the BSD one, that doesn't support the -I
flag. If you use homebrew you can install rm
(and many other GNU coreutils) with brew install coreutils
and the GNU rm
version will be available as grm
. You can then alias it to rm
if you'd like.
If you would rather keep the native implementation of rm
I would suggest using the Z shell as a shell with the oh-my-zsh framework installed. There, you can find many amazing themes to customize your shell with different backgrounds, icons and what's important for avoiding the mistake that concerns us the most in this post: the prompt.
I personally use the agnoster theme, and it gives you a really distinctive prompt that makes it far easier to me to identify when I'm continuing the same command of the previous line or if I'm actually in a new line.
In the screenshot, there is a main prompt filled with blue with the current working directory and an undecorated prompt with a >
sign indicating that we are continuing the line before.
As a third option, you could try to use external CLI tools that instead of removing the files, move them to the trash bin instead. One of the most popular is trash-cli that is available for macOS, Linux, and Windows. The author of that tool, Sindre Sorhus, also wrote a guide with other tricks to avoid accidents with rm
.
I hope this post gives you more options for the next time you are tempted to use rm -rf
and remember to be careful out there!