79

I know how to delete all txt file under current directory by rm *.txt. Does anyone know how to delete all files in current directory EXCEPT txt file?

  • 24
    As always, test the given answers with a harmless command like ls before actually attempting to call rm. – chepner Jun 5 '13 at 15:58
  • ^ This guy doesn't like to live dangerously.. :) – jDub9 Oct 25 at 18:19
115

You can use find:

find . -type f ! -name '*.txt' -delete

Or bash's extended globbing features:

shopt -s extglob
rm *.!(txt)

Or in zsh:

setopt extendedglob
rm *~*.txt(.)
#  ||     ^^^ Only plain files
#  ||^^^^^ files ending in ".txt"
#  | \Except
#   \Everything
  • Some of these may need to be adapted depending on whether you have folders and what you want to do with them. – Kevin Jun 5 '13 at 15:58
  • 1
    Shouldn't *.!(txt) be !(*.txt)? – Lri Jun 6 '13 at 8:32
  • @LauriRanta depends on what's in the folder, which we haven't gotten an answer to. It's fine as is if all the files have extensions, and rm would choke if there were folders. – Kevin Jun 6 '13 at 13:22
  • I've got an issue with the brackets. When I use the globbing style in a bash script, it complains about a syntax error and the parentheses. However doing it from the CLI works. – CMCDragonkai Jan 17 '14 at 8:56
  • 1
    @izogfif check this find . -type f ! -name "*.txt" | xargs -r rm would work in GNU\xargs. BSD and UNIX xargs command may not have -r you have to check your local man xargs – Ntwobike Jun 8 '18 at 7:52
12

If you just want to delete all files except '*.txt' then you can use the following command:

$ find . -type f ! -name "*.txt" -exec rm -rf {} \;

but if you also want to delete directories along with the files then you can use this:

$ find . ! -name "*.txt" -exec rm -r {} \;

10

there are many ways could do it. but the most simple way would be (bash):

shopt -s extglob
rm !(*.txt)
4

One solution without find:

mv dir/*.txt otherdir/
rm -r dir
mv otherdir dir

This should work on all kind of shells.

3

You can use inverted grep and xargs

ls | grep -v .txt$| xargs rm
  • ls | grep -v *.txt | xargs rm works just as well – phillipsk Feb 27 '16 at 13:32
  • @phillipsk grep -v *.txt will work only if there's exactly one .txt file. If there is none, grep will use *.txt as the pattern; if there's more than one, it will search for the first filename inside all of the other .txt files, ignoring the output from ls. (Exact results may depend on the shell's glob options.) – JigglyNaga Jul 21 '16 at 16:11
  • .txt$ will match strings ending with txt regardless of the dot. Because grep takes regular expression as parameter. So files a.txt and aatxt and a-txt will all be matched by this expression. Correct expression should be ls | grep -v \\.txt$ | xargs --no-run-if-empty rm. For curious people: If you want to play around with the expression safely use this test expression ls | grep \\.txt$ | xargs --no-run-if-empty echo (note: there's no -v flag and rm=>echo). Note2: you may have noticed double backslash. One is for regex, another is for bash to escape slash. – Dimitry K Nov 19 '18 at 3:31
1

Simply do:

rm $(ls -I "*.txt" ) #Deletes file type except *.txt

Likewise, if need to delete "except one or more file type", do:

rm $(ls -I "*.txt" -I "*.pdf" ) #Deletes file types except *.txt & *.pdf

  • Welcome to StackExchange! The -I option could be useful, but see why not parse ls. And what does the | xargs achieve? Without any arguments, it just runs echo on all of its input. – JigglyNaga Jul 21 '16 at 15:59
  • What is xargs supposed to achieve? – dhag Jul 21 '16 at 16:00
  • Thanks, xargs was not useful in the above case, have corrected now. – Surya Jul 22 '16 at 22:05
0

This works also to remove all hidden (dot) files and folders except the stated one (.mydir):

rm -rf $(ls -aI ".mydir")

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.