212

I need to find all image files from directory (gif, png, jpg, jpeg).

find /path/to/ -name "*.jpg" > log

How to modify this string to find not only .jpg files?

10 Answers 10

226
find /path/to -regex ".*\.\(jpg\|gif\|png\|jpeg\)" > log
1
  • 12
    Does not work for me on mac, but works with the -E (extended) option (maybe the pipe is an extended feature?): find -E /path/to -iregex ".*\.(jpg|gif|png|jpeg)" > log
    – ling
    Commented Oct 21, 2015 at 7:38
150
find /path/to/  \( -iname '*.gif' -o -iname '*.jpg' \) -print0

will work. There might be a more elegant way.

3
  • 17
    -iname would be case insensitive Commented Nov 21, 2012 at 17:24
  • 1
    @Gerald: It's likely you need to group your OR expression in escaped parentheses: find /path/to/ \( -iname '*.gif' -o -iname '*.jpg' \) -exec ls -l {} \; otherwise the exec only applies to the last part (-iname '*.jpg' in this case). Commented Nov 8, 2018 at 21:50
  • 1
    That's an important remark. find /path/to/ -iname '*.gif' -o -iname '*.jpg' -print0 will only print the jpg files! You need brackets here: find /path/to/ \( -iname '*.gif' -o -iname '*.jpg' \) -print0 Commented Feb 11, 2020 at 16:35
36

find -E /path/to -regex ".*\.(jpg|gif|png|jpeg)" > log

The -E saves you from having to escape the parens and pipes in your regex.

6
  • 3
    my find doesn't have this -E Commented Aug 18, 2014 at 20:58
  • 1
    Hmmm the -E option tells find to use "extended regular expressions". Several other tools have a similar option, but I'm not sure this option is available on all UNIX distributions.
    – tboyce12
    Commented Aug 18, 2014 at 23:12
  • 8
    Works on Mac OS, too. Commented Aug 20, 2014 at 3:32
  • 5
    @tboyce12 Working on ubuntu, I can specify the -regextype to simplify the regex expression: find . -regextype posix-extended -regex ".*\.(jpg|gif|png|jpeg)".
    – doub1ejack
    Commented Oct 23, 2015 at 17:37
  • 1
    @cjm Maybe find -E /path/to -iregex ".*\.(jpg|gif|png|jpeg)" > log. Using the -iregex flag tells find to match case insensitively.
    – tboyce12
    Commented Jan 10, 2017 at 23:58
13
find /path/to/ -type f -print0 | xargs -0 file | grep -i image

This uses the file command to try to recognize the type of file, regardless of filename (or extension).

If /path/to or a filename contains the string image, then the above may return bogus hits. In that case, I'd suggest

cd /path/to
find . -type f -print0 | xargs -0 file --mime-type | grep -i image/
1
  • Sorry, had an errant click there and I apparently can't undo the downvote... :( Commented Apr 23, 2016 at 15:56
10
find /path -type f \( -iname "*.jpg" -o -name "*.jpeg" -o -iname "*gif" \)
4
  • 2
    Could you explain why you added the (escaped) parentheses around the name/iname parameters?
    – user793458
    Commented Apr 12, 2017 at 14:16
  • Any reason for the inconsistency? -iname *.jpg, -o -name *.jpeg, -o -iname *gif all have a slightly different format. Commented Apr 26, 2018 at 6:15
  • if you could at least explain differencies with other answers.
    – el-teedee
    Commented May 1, 2019 at 21:50
  • -o - logical OR. Not an inconsistency, just joins together the -iname clauses. -iname "*gif" would match a filename ending foogif, whereas -iname "*.gif" would not.
    – asinoladro
    Commented Jul 25, 2022 at 17:57
9

On Mac OS use

find -E packages  -regex ".*\.(jpg|gif|png|jpeg)"
6

In supplement to @Dennis Williamson 's response above, if you want the same regex to be case-insensitive to the file extensions, use -iregex :

find /path/to -iregex ".*\.\(jpg\|gif\|png\|jpeg\)" > log
3
find -regex ".*\.\(jpg\|gif\|png\|jpeg\)"
1

Adding -regextype posix-extended option only worked in my case:

sudo find . -regextype posix-extended -regex ".*\.(css|js|jpg|jpeg|png|ico|ttf|woff|svg)" -exec chmod 0640 {} \;
0

in case files have no extension we can look for file mime type

find . -type f -exec file -i {} + | awk -F': +' '{ if ($2 ~ /audio|video|matroska|mpeg/) print $1 }'

where (audio|video|matroska|mpeg) are mime types regex

&if you want to delete them:

find . -type f -exec file -i {} + | awk -F': +' '{ if ($2 ~ /audio|video|matroska|mpeg/) print $1 }' | while read f ; do
  rm "$f"
done

or delete everything else but those extensions:

find . -type f -exec file -i {} + | awk -F': +' '{ if ($2 !~ /audio|video|matroska|mpeg/) print $1 }' | while read f ; do
  rm "$f"
done

notice the !~ instead of ~

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