Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I am attempting to exclude .svg and .jpg files from my find command however it still returns both of them. What am I doing wrong?

find . \( ! -iname \*\.svg -o ! -iname \*\.jpg \)
share|improve this question
Careful, bash (and other) shells use '!' for repeating old commands. Some bash versions don't even allow to quote it. – vonbrand Jan 11 '13 at 17:37
up vote 2 down vote accepted

Your logic is flawed: With the command you have right now, you find every non-.svg or every non-.jpg file. What you wrote reads as:

find (everything that's not an SVG or everything that's not a JPG)

So you'll get the JPG files, because find already evaluated the first part and gave you everything that's not an SVG file. Because of the way the options are parsed, if the first part of an or expression evaluates to true, the second part is not even looked at.

In essence, once find returns you everything that's not an SVG, it doesn't care about what you want with the JPG files.

The correct way to phrase this would be with a logical and:

find . \( ! -iname '*.svg' -a ! -iname '*.jpg' \)

This reads as:

find (everything that's not an SVG and everything that's not a JPG)

Or, by negating the whole expression:

find . ! \(-iname '*.svg' -o -iname '*.jpg' \)

Which reads as:

find everything that's not (an SVG or a JPG)

Note that you can skip escaping the * if you simply put it in single or double quotes, e.g. -iname '*.jpg'. This is much easier to read.

share|improve this answer
Awesome. I was using -o blindly not knowing it stood for OR. Now I know. – PeanutsMonkey Jan 11 '13 at 10:40

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.