30

Let's say I have a directory tree like this:

FOLDER:
    file1
    file2
    file3
    Subfolder1:
        file1
        file2
    Subfolder2:
        file1
        file2

If I used rm -r FOLDER/*, everything in FOLDER would be deleted including sub-directories. How can I delete all files in FOLDER and in its sub-directories without deleting actual directories?

Sergiy Kolodyazhnyy
  • 103,293
  • 19
  • 273
  • 492
PKM
  • 789
  • 2
  • 12
  • 23

3 Answers3

47

What you're trying to do is recursive deletion. For that you need a recursive tool, such as find.

find FOLDER -type f -delete
Zanna
  • 69,223
  • 56
  • 216
  • 327
Sergiy Kolodyazhnyy
  • 103,293
  • 19
  • 273
  • 492
15

With bash:

shopt -s globstar  ## Enables recursive globbing
for f in FOLDER/**/*; do [[ -f $f ]] && echo rm -- "$f"; done

Here iterating over the glob expanded filenames, and removing only files.

The above is dry-run, if satisfied with the changes to be made, remove echo for actual removal:

for f in FOLDER/**/*; do [[ -f $f ]] && rm -- "$f"; done

Finally, unset globstar:

shopt -u globstar

With zsh, leveraging glob qualifier:

echo -- FOLDER/**/*(.)

(.) is glob qualifier, that limits the glob expansions to just regular files.

The above will just print the file names, for actual removal:

rm -- FOLDER/**/*(.)
heemayl
  • 90,425
  • 20
  • 200
  • 267
11

If your version of find doesn't support -delete you can use the following to delete every file in the current directory and below.

find . ! -type d -exec rm '{}' \;
  • `-exec rm {} +` would be faster, especially if there are lots of files. – muru Nov 20 '16 at 04:14
  • And `find . ! -type d -exec rm {} +` removes sym links as well. – DK Bose Nov 20 '16 at 04:37
  • 1
    @muru: If a particular implementation of `find` doesn't support `-delete` it probably doesn't support `-exec ... {} +` either. The recommended way to deal with that is `find ... -print0 | xargs -r0 rm` (if one expects many potential matches). – David Foerster Nov 20 '16 at 13:02
  • 5
    @DavidFoerster not really. `-exec ... {} +` is POSIX, but `-delete` isn't. (Neither is `-print0`, by the way.) – muru Nov 20 '16 at 13:13
  • @muru: Fair enough. I've encountered at least two non-POSIX `find` implementations that supported `-print0` but not `-exec ... {} +` (I don't remember about `-delete` though). One was on OS X, the other on Solaris (a few years ago on a very conservatively updated system). You can also substitute `-print0` with `-printf '%p\0'`. Anyway, this is Ask*Ubuntu* and not [Unix.SE] and Ubuntu uses GNU find since forever. – David Foerster Nov 20 '16 at 13:26
  • One that is even faster due to not forking for every rm: find . ! -type d -print0|xargs -0 -n50 rm -f . That will delete 50 filenames at a time, and delimit with \0 just in case some filenames have spaces or other characters. – lsd Nov 21 '16 at 15:32