23

Will rm -rf * remove all files/folders in the current directory ? I want to make sure the wildcard * won't move up in upper directories and erase all my filesystem. :D

I remember doing chmod 777 .* -R to chmod hidden files and it chmoded all my filesystem. Obviously, I was on the root account.

gadgetmo
  • 786
  • 4
  • 9
  • 25

7 Answers7

17

No, if you did not tweak your shell a lot this will not remove files or directories starting with a .. To remove them, too, you can either list them explicitly

rm -rf .file .dir

or use the right glob patterns (thanks Chris)

rm -rf .[^.]* ..?*

EDIT The point here is that you cannot use .* to match files like .file, because .* or .*? will also match .. or .. .[^.]* matches files like .file, while ..?* matches files like ..foo (* matches zero or more characters while ? matches exactly one).

14

If you want to remove a directory and all its contents, you can chdir into the parent directory and them rm -rf that directory by name, bypassing the entire globbing question. If you want to remove the contents but keep the directory, it's easiest to remove all and then recreate the directory.

It is complex to come up with a glob that will match all possible directory entries save . and ..; it's easy to come up with a simple answer (e.g., * .??*) that will work almost always in practice. This is OK for interactive use, since it's easy to remember and the times it doesn't work can be caught with a post-rm ls -a. For a script, it's easier to do the remove all and recreate the empty directory.

mpez0
  • 2,842
10

Since I think this question is more about what * does (and not rm), let's try another approach.


If you are unsure what the * does, you can "test" first using a harmless command like echo. Before you run this, try to guess what they will show if you run them in your home dir.

echo *
echo .*

But first let's create a playground so we can play with the stars and see what we end up with.

mkdir ~/star_test/
cd ~/star_test/
>.file1
>file2

Now in this dir we have this:

cj@zap:~/star_test$ ls -1a
.
..
.file1
file2

Now notice what the * expands into using the echo command:

cj@zap:~/star_test$ echo *
file2
cj@zap:~/star_test$ echo .*
. .. .file1

So let's see what happens with the rm command

cj@zap:~/star_test$ rm -rf *
cj@zap:~/star_test$ ls -1a
.
..
.file1

As you see he did only remove the file2, since * only expanded to file2. If you would type rm -rf .* that would be the same as writing

rm -rf . .. .file1

And to be honest, that do not look fun ;)

Hope this clarifies the * part of your question.


Update: However as Ankur Goel points out there is some kind of protection built into rm (kind of unusual for shell commands :)

Let's create a new playground:

cd ~/star_test/
mkdir -p test1/test2/test3
sudo chown root.root test1
cd test1/test2/test3/
>.file1
>file2

So now we have this again, but with test1 owned by root as protection if rm start to go berserk.

cj@zap:~/star_test/test1/test2/test3$ ls -a
.  ..  file2  .file1
cj@zap:~/star_test/test1/test2/test3$ echo .*
. .. .file1

So let's remove everything:

cj@zap:~/star_test/test1/test2/test3$ rm -rf .*
rm: cannot remove directory `.'
rm: cannot remove directory `..'
cj@zap:~/star_test/test1/test2/test3$ ls -a
.  ..  file2

And it looks like rm did not remove . and .. even if we told him to!!!

So after this long answer it turns out to be safe to remove everything in a dir with this:

rm -rf * .*

But I would use this with care, since I'm not sure all implementations of rm behaves like this!

Johan
  • 5,515
8

Yes. rm -rf will only delete files and folders in the current directory, and will not ascend up the file tree. rm will also not follow symlinks and delete the files they point to, so you don't accidentally prune other parts of your filesystem.

1

A much easier way to empty an entire folder, also avoiding the "too many arguments" issues discussed in this answer, is to simply delete and recreate the directory itself. To make sure this works correctly when you are in a symlinked directory, use the following lines:

cd ..
rm -rf $(readlink -f yourdir) #remove the directory, treat the case of a symlink
                        # by using readlink, to recreate the linked-to directory
mkdir $(readlink -f yourdir) # recreate the directory to have it empty
cd yourdir

(If you uses yourdir instead of $(readlink -f yourdir) you'd only replace the link while the original location remains full)

0

If you don't want to move one level up like mpez0 said and rm -rf this specific folder, there is a way to work on all directories/files except . and .. in the current folder by doing:

rm -rf $(ls -A)

Of course, if any of the directories/files contains one of the characters in the shell IFS special variable (e.g. space, tab, newline), you might want to change the IFS first, run the command, then restore IFS.

tzot
  • 746
0

There is a hidden problem when using * in Unix shell:

When you have file names start with a dash (-), these file names could be mistakenly interpreted as options by the programs, such as rm(1).

In this case, for example, if you have a file named -f in working directory, this file won't be removed by rm -rf *, as it will be treated as another -f option by rm(1); or having a file named -i would negating the effect of your early specified -f.

GNU operating systems are more likely to be affected by this issue, because its getopt(3) functions won't stop at first non-option argument, when looking for options; as a result, even you put * after some non-options, on a GNU system (or using GNU rm since it has their own getopt(3) implementation that behaves very similar to the one in GLIBC), strangely-named files may still be interpreted as options.

Based on Benjamin Bannier's answer, to really remove all files in working directory, put a -- before file names, like

rm -rf -- .[^.]* ..?* *

Further reading:

UNIX-HATERS Handbook, section 2, Welcome, User!, Consistently Inconsistent.

Low power
  • 327
  • 3
  • 6