Updated: 10 October 2026 · Applies to: GNU rm 9.5 (AlmaLinux 10) and 9.7 (Debian 13, Ubuntu 26.04), GNU find 4.10.0, bash 5.2 and 5.3; the same commands work on Ubuntu 24.04, Rocky Linux and RHEL

To remove all files with one extension in the current folder, run rm *.log. To remove them from all subfolders as well (recursively), use find . -type f -name '*.log' -delete. To empty a folder completely, hidden files included, run find /path/to/folder -mindepth 1 -delete, and to delete a folder together with everything in it, run rm -r folder (rmdir only removes empty folders).

rm *.log
find . -type f -name '*.log' -delete
find /path/to/folder -mindepth 1 -delete
rm -r folder

Linux has no recycle bin on the command line: deleted files are gone. Preview first. Run the find command without -delete, or replace rm with ls, and check the list before you delete anything.

The examples use this test folder on Debian 13 (Ubuntu 26.04 and AlmaLinux 10 gave the same results):

.env  app.log  error.log  keep.zip  notes.txt  photo.JPG  report.odt
cache/a.log  cache/b.tmp  cache/old/c.log

1. Remove all files with an extension in one folder

$ rm -v *.log
removed 'app.log'
removed 'error.log'

-v lists each file as it is removed. Only the current folder is affected: cache/a.log stays. Some notes:

  • Several extensions: rm -v *.log *.tmp. If one pattern matches nothing, rm reports cannot remove '*.tmp': No such file or directory and still removes the rest.
  • Patterns are case-sensitive: *.jpg does not match photo.JPG.
  • Another folder: rm /var/www/uploads/*.tmp.

2. Delete files by extension recursively

  1. List what will be deleted:
    $ find . -type f -name '*.log'
    ./cache/old/c.log
    ./cache/a.log
    ./app.log
    ./error.log
  2. Delete the same files by adding -delete at the end:
    find . -type f -name '*.log' -delete

Keep the quotes around '*.log', so that find receives the pattern instead of the shell expanding it. Useful variations:

  • See each file as it goes: find . -type f -name '*.log' -exec rm -v {} +
  • Several extensions: find . -type f \( -name '*.log' -o -name '*.tmp' \) -print -delete
  • Any case (.jpg, .JPG): use -iname '*.jpg'.
  • Only files older than 30 days: add -mtime +30 before -delete.

"Argument list too long": with very many files, rm *.tmp fails before rm even starts. In our test with 150,000 files, bash stopped with /usr/bin/rm: Argument list too long (the limit, getconf ARG_MAX, was 2,097,152 bytes). find . -maxdepth 1 -name '*.tmp' -delete removed all of them in about 7 seconds, because find does not pass the names on a command line.

3. Remove all files in a directory

rm folder/* removes the files but stops at subfolders, and * never matches hidden names such as .env or .htaccess:

$ rm -v /srv/demo/*
removed '/srv/demo/app.log'
rm: cannot remove '/srv/demo/cache': Is a directory
removed '/srv/demo/error.log'
...
$ ls -A /srv/demo
.env
cache

(output shortened) Choose the command that matches what you want to keep:

  • Everything inside, keep the folder itself: find /srv/demo -mindepth 1 -delete. This also removes hidden files and subfolders; afterwards ls -A /srv/demo printed nothing and the empty folder was still there.
  • Everything except hidden files: rm -rv /srv/demo/* (it left .env in our test).
  • Only the files, not the subfolders: find /srv/demo -maxdepth 1 -type f -delete
  • With rm, hidden files included: shopt -s dotglob first (bash), then rm -rv /srv/demo/*, then shopt -u dotglob.

4. rmdir and all contents: delete a folder and everything in it

$ rmdir demo
rmdir: failed to remove 'demo': Directory not empty
$ rm demo
rm: cannot remove 'demo': Is a directory

rmdir and rm -d remove empty folders only. For a folder with contents, use rm -r (recursive). It asks before each write-protected file; rm -rf never asks, so check the path twice. A safer middle way is rm -rI demo, which asks once before it starts (rm: remove 1 argument recursively?). What each flag does is explained in what rm -rf does, and deleting folders by name across a whole tree in search and remove directories recursively.

5. Delete all files except one or a few

With find (works in any shell). Preview with -print only, then add -delete:

$ find . -maxdepth 1 -type f ! -name '*.zip' -print -delete
./notes.txt
./photo.JPG
./app.log
./report.odt
./error.log
./.env

Everything except keep.zip went, including the hidden .env. To keep several patterns, group them: find . -type f ! \( -name '*.zip' -o -name '*.odt' \) -delete. Without -maxdepth 1, this also deletes files in subfolders.

With bash extended globbing:

shopt -s extglob
rm -v !(keep.zip|report.odt)
shopt -u extglob

This keeps the two names, skips subfolders (rm: cannot remove 'cache': Is a directory) and leaves hidden files alone. In a script, shopt -s extglob must be on its own line before the line that uses !( ); on the same line, bash fails with syntax error near unexpected token `('.

With GLOBIGNORE: GLOBIGNORE='*.zip:*.odt'; rm -v *; unset GLOBIGNORE keeps the matching files, but be careful: setting GLOBIGNORE makes * match hidden files too. In our test it removed .env.

6. Avoid the common accidents

  • Put -delete last. find works left to right, so find . -delete -name '*.log' deletes every file and folder below the current one. We tried it: the test folder was empty afterwards.
  • Guard variables in scripts. If $DIR is empty, rm -rf "$DIR"/* becomes rm -rf /*. Write rm -rf "${DIR:?}"/*: bash then stops with DIR: parameter null or not set instead.
  • rm -rf / itself is refused by default (rm: it is dangerous to operate recursively on '/'), but /* is not protected.
  • Patterns with * behave differently in find, ls and rm; see how to use wildcards safely.

If something important was deleted by mistake, stop writing to that disk and follow how to recover a deleted file in Linux. A recent backup is the only reliable way back.

Ucartz services for this topic

Was this answer helpful? 0 Users Found This Useful (0 Votes)