Bash – How to remove all files in a directory except hidden ones

bashrm

I'm cleaning an output directory before I put things in it. I want to track the output directory in git with a .gitkeep file, but this keeps on getting deleted with my rm -rf "$OUT_DIR" line in a bash script.

Is there a way to remove the contents of a directory but keep either hidden files or somehow just keep that .gitkeep file?

Best Answer

By default bash doesn't glob dot-files, so to remove everything but hidden files in bash, using rm:

rm *

Sample output:

~/tmp$ ls -la
total 8
drwxrwxr-x  2 user user 4096 giu 11 20:00 .
drwxr-xr-x 21 user user 4096 giu 11 08:26 ..
-rw-rw-r--  1 user user    0 giu 11 20:00 .1
-rw-rw-r--  1 user user    0 giu 11 20:00 2
-rw-rw-r--  1 user user    0 giu 11 20:00 3
-rw-rw-r--  1 user user    0 giu 11 20:00 4
-rw-rw-r--  1 user user    0 giu 11 20:00 5
~/test$ rm *
~/tmp$ ls -la
total 8
drwxrwxr-x  2 user user 4096 giu 11 20:00 .
drwxr-xr-x 21 user user 4096 giu 11 08:26 ..
-rw-rw-r--  1 user user    0 giu 11 20:00 .1

To remove everything but .gitkeep in bash, enabling globbing for dot-files and using rm:

shopt -s dotglob
rm !(.gitkeep)

Sample output:

~/tmp$ ls -la
total 8
drwxrwxr-x  2 user user 4096 giu 11 20:19 .
drwxr-xr-x 21 user user 4096 giu 11 08:26 ..
-rw-rw-r--  1 user user    0 giu 11 20:19 1
-rw-rw-r--  1 user user    0 giu 11 20:19 2
-rw-rw-r--  1 user user    0 giu 11 20:19 3
-rw-rw-r--  1 user user    0 giu 11 20:19 4
-rw-rw-r--  1 user user    0 giu 11 20:19 5
-rw-rw-r--  1 user user    0 giu 11 20:19 .gitkeep
-rw-rw-r--  1 user user    0 giu 11 20:19 .hidden
~/tmp$ shopt -s dotglob
~/tmp$ rm !(.gitkeep)
rm: cannot remove ‘.’: Is a directory
rm: cannot remove ‘..’: Is a directory
user@user-X550CL:~/tmp$ ls -la
total 8
drwxrwxr-x  2 user user 4096 giu 11 20:20 .
drwxr-xr-x 21 user user 4096 giu 11 08:26 ..
-rw-rw-r--  1 user user    0 giu 11 20:19 .gitkeep
Related Question