270

I can get all jpg images by using:

find . -name "*.jpg"  

But how can I add png files to the results as well?

Michael Mrozek
  • 91,316
  • 38
  • 238
  • 232
wong2
  • 3,493
  • 3
  • 17
  • 8

5 Answers5

324

Use the -o flag between different parameters.

find ./ -type f \( -iname \*.jpg -o -iname \*.png \) works like a charm.

NOTE There must be a space between the bracket and its contents or it won't work.

Explanation:

  • -type f - only search for files (not directories)
  • \( & \) - are needed for the -type f to apply to all arguments
  • -o - logical OR operator
  • -iname - like -name, but the match is case insensitive
Shadur
  • 30,641
  • 11
  • 58
  • 69
  • 2
    Do you need the parentheses. The command works for me without them. Are they needed for some shells? – MikeD Mar 19 '17 at 02:25
  • 4
    @miked The command will "work" without them, yes, but you'd wind up getting hits on directories that end in .png as well as files that end with .jpg, which is not exactly what was intended. – Shadur Mar 19 '17 at 08:25
  • 1
    Thanks for clarifying! The `type -f` does not extend and apply to both expressions without the parentheses, So, `find ./ -type f -iname \*.jpg -o -type f -iname \*.png` also works ... although it's two characters longer :-) – MikeD Mar 19 '17 at 11:58
  • 6
    It's a matter of operator precedence. Just like `a * b + c` is different from `a * (b + c)` – Shadur Mar 19 '17 at 12:13
  • 1
    Thanks, and I have rewritten `a * (b + c)` as `a * b + a * c` with: `find ./ -type f -iname \*.jpg -o -type f -iname \*.png` – MikeD Mar 19 '17 at 12:22
146

You can combine criteria with -o as suggested by Shadur. Note that -o has lower precedence than juxtaposition, so you may need parentheses.

find . -name '*.jpg' -o -name '*.png'
find . -mtime -7 \( -name '*.jpg' -o -name '*.png' \)  # all .jpg or .png images modified in the past week

On Linux, you can use -regex to combine extensions in a terser way. The default regexp syntax is Emacs (basic regexps plus a few extensions such as \| for alternation); there's an option to switch to extended regexps.

find -regex '.*\.\(jpg\|png\)'
find -regextype posix-extended -regex '.*\.(jpg|png)'

On FreeBSD, NetBSD and OSX, you can use -regex combined with -E for extended regexps.

find -E . -regex '.*\.(jpg|png)'
Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
59

This is more correct:

find . -iregex '.*\.\(jpg\|gif\|png\|jpeg\)$'
Dimitry
  • 607
  • 5
  • 2
  • 16
    Why do you say it is "more" correct? – Kevin Nov 17 '12 at 03:51
  • 5
    @Kevin I guess because `-iregex` matches `jpg` as well as `JPG Jpg jpG` and such. I think the `$` isn't needed. – ott-- May 19 '15 at 10:41
  • 1
    This works fine on [MinGW](http://en.wikipedia.org/wiki/MinGW). – Peter Mortensen Sep 18 '15 at 11:30
  • 2
    First, you omitted the search folder as first argument which will throw an error. Secondly, on OSX escaping the parenthesis will not work, and this should be used instead: `find -E . -iregex '.*\.(jpg|png|gif)'` as shown in @sorin's answer. – ccpizza Nov 11 '17 at 11:36
  • Much better than the stupid `-o` operator and it's more correct since you have to use the right tool for the job. – pouya Apr 22 '22 at 14:57
  • `-o` isn't stupid; it does exactly what the `or` operator is supposed to do. And the "right" tool for the job is whatever gets the job done. – Shadur Sep 23 '22 at 13:01
21

To make it clear, the only option that works on Linux, Unix and macOS flavour is:

find -E . -regex '.*\.(jpg|png)'

That's because the OS X version is a little bit different, but that's important to write things that go well on most platforms.

sorin
  • 1,219
  • 2
  • 14
  • 18
3

If only files are needed:

find ./ -type f -regex '.*\.\(jpg\|png\)$'

For example, this will not match a directory named "blah.jpg".

nvd
  • 183
  • 4