rm -rf all files and all hidden files without . & .. error

rm -rf /some/path/* deletes all non-hidden files in that dir (and subdirs).

rm -rf /some/path/.* deletes all hidden files in that dir (but not subdirs) and also gives the following error/warning:

rm: cannot remove directory: `/some/dir/.'
rm: cannot remove directory: `/some/dir/..'

What is the proper way to remove all hidden and non-hidden files and folders recursively in a target directory without receiving the warning/error about . and ..?

Asked By: Jake Wilson


Either change the dotglob option of your shell and use *, or use something like find.

find somedir -mindepth 1 -delete

You could always send error messages to /dev/null

rm -rf /some/path/.* 2> /dev/null

You could also just

rm -rf /some/path/
mkdir /some/path/

…then you won’t have to bother with hidden files in the first place.

Answered By: evilsoup

Find is your friend.

find ! -name '.' ! -name '..' -delete

% find ! -name '.' ! -name '..'
% find ! -name '.' ! -name '..' -delete    
% find ! -name '.' ! -name '..'     

If you wish to use recursively search something other your current directory ($PWD), then add a path right after the find command; e.g., find /path ! -name '.' ! -name '..' -delete. If you only want to descend n number of directories, then use the -maxdepth n option right after the /path parameter.

The above command was tested on an Ubuntu 13.04 system. Will likely work on other, modern linux systems.

Answered By: laebshade

* matches all non-dot-files, .[!.]* matches all dot files except . and files whose name begins with .., and ..?* matches all dot-dot files except ... Together they match all files other than . and ... If any of these three patterns matches nothing, it expands to itself; rm -f doesn’t care about non-existent arguments, so this doesn’t matter.

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

You can also use find. This is more complex but has the advantage of working even if there are so many files that the wildcards above would expand beyond your system’s command line length limit.

find . -name . -o -prune -exec rm -rf -- {} +

You may find it clearer to remove and recreate the directory. This has the advantage (or downside, as the case may be) of resulting in an empty directory even if another program is concurrently creating files in the original directory.

Just realised this is the most convenient way in most Linux distros:

ls -A1 | xargs rm -rf


-A = list everything except . and ..

-1 = put every item in one line

Answered By: godzillante

This should work just like @Gilles answer but more compact:

rm -rf {,.[!.],..?}*


rm -rf dir/to/files/{,.[!.],..?}*

should also add an if for usage in scripts just to be safe:

if [ -d "$DIR" ]; then
    rm -rf ${DIR}/{,.[!.],..?}*
Answered By: Paweł Prażak

I suggest you experiment with

Turn-ON dots (hidden files)

  • set dotglob

    shopt -s dotglob

Turn-OFF dots

  • unset dotglob

    shopt -u dotglob

This method worked exactly as I wished for a copy command that was missing the hidden directories.

    shopt -s    dotglob
    cp    -rvn  ./$from/*  ./$too/
    shopt -u    dotglob

So I did a remove (delete), and oops

    shopt -s    dotglob
    rm -fr ../message_splitter--044a/*
    shopt -u    dotglob

that works too!

It occurs to me that you dear reader can’t see the message_splitter directory. Any way it has a .svn folder that needs to be removed, and copied Into.

From man page

dotglob If set, bash includes filenames beginning with a `.’ in the results of pathname expansion.


Answered By: will

What is the proper way to remove all hidden and non-hidden files and folders recursively in a target directory without receiving the warning/error about . and ..?

Assuming the directory in question is ./dir, then

rm -rf ./dir

would remove all files in ./dir, including hidden files and directories, recursively, and including the ./dir directory itself.

If you do not want to delete the directory itself, then you may just recreate it afterwards, or use

find ./dir -mindepth 1 -delete

or if you find does not support -delete,

find ./dir -mindepth 1 -depth -exec rm -rf {} ';'

Using -mindepth 1 allows you to keep the top-level directory ./dir.

Answered By: Kusalananda

Why nobody mentions:

rm -rf * .*
Answered By: Qian Chen

What about using find with both -maxdepth and -mindepth?
This can be also run outside the directory you want to clear.

find target/ -maxdepth 1 -mindepth 1 -exec rm -fr -- {} +;

Here’s a complete example:

mkdir -p target/{plain{0..3},.hidden{0..3}}; 
touch target/{plain{0..3},.hidden{0..3}} target/{plain{0..3},.hidden{0..3}}/{plain{0..3},.hidden{0..3}};
tree -a;
find target/ -maxdepth 1 -mindepth 1 -exec rm -fr -- {} +;
tree -a;
Answered By: user1702341

Shorter version

rm -r * .*

rm: remove

-r: recursively

*: all directories

.*: all hidden directories ( ex: .git, .gitignore )

use an optional force flag ( --force or -f ). Check the usage here.

rm -rf * .*

Note: ( for zsh users )
The above command doesn’t work partially i.e If it can’t find files/ directories matching any of * or .* the other one won’t execute.

You can fix this using the command

setopt no_nomatch

zsh commands are scoped to a session(/tab). ( if you open a new session you will still face the issue ).

add this line to .zshrc file to apply for all sessions.

ps: restart iterm after making changes to .zshrc

Answered By: Anjan Talatam

the find command of the other answer did not work for me as it tries to remove the directory itself. I found this one works better:

remove() {
  find "$1" ! -name "$1" -a -prune -exec rm -rfv -- {} +

remove foobar

Note, you must not include a / at the end of the directory, otherwise it will try to remove the directory as well.

You can use -wholename instead of -name if your path starts with /.

The v of the rm command prints out the files as they are being deleted.

Answered By: Josua Krause
Categories: Answers Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.