Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Can I modify the rm command with regular expression or something to delete every file in current directory except files with extensions *.bmp, *.wav and *.png? It should be case insensitive because there are files like *.BMP or *.bMP.

thank you

share|improve this question
mv all *.bmp, *.wav, *.png to newdir. Then rm -rf dir. –  kev Dec 27 '11 at 14:37

3 Answers 3

up vote 8 down vote accepted

@ChrisDown has given a solution that take into account the difference of files and directories, and also if there is no file to remove.

Given that rm would fail however in these situations, the command could be simplified as

shopt -s extglob nocaseglob
rm !(*.bmp|*.wav|*.png)

Remember to reset the two shell options to their default values. In my case extglob is already set on interactive shells, so I only need

shopt -u nocaseglob

If you would to see in advance what files will be removed, simply substitute the rm with echo.

share|improve this answer
@enzolib This is already out of the scope of the question, but I used commas instead of | and everything from the directory was deleted (nothing important, so I downloaded it again), but I can imagine the danger of this command. Is there some less severe command with possibility of backup? –  xralf Dec 28 '11 at 10:49
@enzolib I see you edited the question and your last sentence is very useful. –  xralf Dec 28 '11 at 10:51

If you are using bash, you can use a combination of extglob and nocaseglob.

shopt -s extglob nocaseglob
for file in !(@(*.bmp|*.wav|*.png)); do
    [[ -f "${file}" ]] && files+=( "${file}" )
(( ${#files[@]} )) && rm "${files[@]}"

Otherwise you can us something like the following:

find . -maxdepth 1 -type f ! \( -iname '*.bmp' -o -iname '*.wav' -o \
    -iname '*.png' \) -delete
share|improve this answer
-exec rm {} can be replaced with -delete –  akond Dec 27 '11 at 14:42
Thank you for this complex command. Actually I was looking for something more simple, to be able to use it quickly, when I have a need. So enzolib's solution is more convenient for my common needs. –  xralf Dec 27 '11 at 17:16
@xralf Bear in mind that that will not only remove regular files, however... –  Chris Down Dec 27 '11 at 20:37
@ChrisDown That's quite strange, because I usually have to use rm -r to remove directories. –  xralf Dec 28 '11 at 10:54
@xralf It's not only directories that are not regular files. –  Chris Down Dec 28 '11 at 11:08

I would suggest that you take a little time and do this in multiple steps so you do not do anything accidently silly.

  1. create a command to identify the files you want to delete, e.g.

        ls | grep -v *.bmp | grep -v *.wav  # current directory


        find . -type f | grep -v *.bmp      # current and sub directories

    if the list of returned files is what you want to remove, then

  2. recall the last command and add the xargs rm command to it, e.g.

        ls | grep -v *.bmp | grep -v *.wav | xargs rm
share|improve this answer
I don't understand why you consider using grep -v instead of find's inbuild ! -iname any safer. Not to mention that this doesn't work in a case-insensitive fashion as requested in the question, and will break on newlines. –  Chris Down Dec 27 '11 at 22:16

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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