Unix command deleted every directory even though not specified
The -r
argument means "delete recursively" (ie descend into subdirectories). The -f
command means "force" (in other words, don't ask for confirmation). -rf
means "descend recursively into subdirectories without asking for confirmation"
ls -l
lists all files in the directory. xargs
takes the input from ls -l
and appends it to the command you pass to xargs
The final command that got executed looked like this:
rm -rf bark.* <output of ls -l>
This essentially removed bark.*
and all files in the current directory. Moral of the story: be very careful with rm -rf
. (You can use rm -ri
to ask before deleting files instead)
rm(1)
deleted every file and directory in the current working directory because you asked it to.
To see roughly what happened, run this:
cd /etc ; ls -l | xargs echo
Pay careful attention to the output.
I strongly recommend using echo
in place of rm -rf
when constructing command lines. Only if the output looks fine should you then re-run the command with rm -rf
. When in doubt, maybe just use rm -r
so that you do not accidentally blow away too much. rm -ir
if you are very skeptical of your command line. (I have been using Linux since 1994 and I still use this echo
trick when constructing slightly complicated command lines to selectively delete a pile of files.)
Incidentally, I would avoid parsing ls(1)
output in any fashion -- filenames can contain any character except ASCII NUL
and /
chars -- including newlines, tabs, and output that looks like ls -l
output. Trying to parse this with tools such as xargs(1)
can be dangerous.
Instead, use find(1)
for these sorts of things. To delete all files in all directories named bark.*
, I'd run a command like this:
find . -type d -name 'bark.*' -print0 | xargs -0 rm -r
Again, I'd use echo
in place of rm -r
for the first execution -- and if it looked fine, then I'd re-run with rm -r
.
The ls -l
command gave a list of all the subdirectories in your current present-working-directory (PWD).
The rm
command can delete multiple files/directories if you pass them to it as a list.
eg: rm test1.txt test2.txt myApp
will delete all three of the files with names:
test1.txttest2.txtmyApp
Also, the flags for the rm
command you used are common in many a folly.rm -f
- Force deletion of files without asking or confirmingrm -r
- Recurse into all subdirectories and delete all their contents and subdirectories
So, let's say you are in /home/user, and the directory structure looks like so:
/home/user|->dir1|->dir2`->file1.txt
the ls -l
command will provide the list containing "dir1 dir2 file1.txt"
, and the result of the command ls -l | xargs rm -rf
will look like this:rm -rf dir1 dir2 file1.txt
If we expand your original question with the example above, the final command that gets passed to the system becomes:rm -rf di1 dir2 file1.txt bark.*
So, everything in the current directory gets wiped out, so the bark.*
is redundant (you effectively told the machine to destroy everything in the current directory anyway).
I think what you meant to do was delete all files in the current directory and all subdirectories (recurse) that start with bark.
To do that, you just have to do:find -iname bark.* | xargs rm
The command above means "find all files in this directory and subdirectories, ignoring UPPERCASE/lowercase/mIxEdCaSe, that start with the characters "bark.", and delete them". This could still be a bad command if you have a typo, so to be sure, you should always test before you do a batch-deletion like this.
In the future, first do the following to get a list of all the files you will be deleting first to confirm they are the ones you want deleted.find -iname bark.* | xargs echo
Then if you are sure, delete them viafind -iname bark.* | xargs rm
Hope this helps.
As a humorous note, one of the most famous instances of "rm -rf" can be found here:https://github.com/MrMEEE/bumblebee-Old-and-abbandoned/commit/a047be85247755cdbe0acce6f1dafc8beb84f2ac
An automated script runs something like rm -rf /usr/local/.........
, but due to accidentally inserting a space, the command became rm -rf /usr /local/......
, so this effectively means "delete all root folders that start with usr or local", effectively destroying the system of anyone who uses it. I feel bad for that developer.
You can avoid these kinds of bugs by quoting your strings, ie:rm -rf "/usr/ local/...."
would have provided an error message and avoided this bug, because the quotes mean that everything between them is the full path, NOT a list of separate paths/files (ie: you are telling rm that the file/folder has a SPACE character in its name).