How to use regex with find command?

RegexLinuxFind

Regex Problem Overview


I have some images named with generated uuid1 string. For example 81397018-b84a-11e0-9d2a-001b77dc0bed.jpg. I want to find out all these images using "find" command:

find . -regex "[a-f0-9\-]\{36\}\.jpg".

But it doesn't work. Something wrong with the regex? Could someone help me with this?

Regex Solutions


Solution 1 - Regex

find . -regextype sed -regex ".*/[a-f0-9\-]\{36\}\.jpg"

Note that you need to specify .*/ in the beginning because find matches the whole path.

Example:

susam@nifty:~/so$ find . -name "*.jpg"
./foo-111.jpg
./test/81397018-b84a-11e0-9d2a-001b77dc0bed.jpg
./81397018-b84a-11e0-9d2a-001b77dc0bed.jpg
susam@nifty:~/so$ 
susam@nifty:~/so$ find . -regextype sed -regex ".*/[a-f0-9\-]\{36\}\.jpg"
./test/81397018-b84a-11e0-9d2a-001b77dc0bed.jpg
./81397018-b84a-11e0-9d2a-001b77dc0bed.jpg

My version of find:

$ find --version
find (GNU findutils) 4.4.2
Copyright (C) 2007 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Eric B. Decker, James Youngman, and Kevin Dalley.
Built using GNU gnulib version e5573b1bad88bfabcda181b9e0125fb0c52b7d3b
Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION FTS() CBO(level=0) 
susam@nifty:~/so$ 
susam@nifty:~/so$ find . -regextype foo -regex ".*/[a-f0-9\-]\{36\}\.jpg"
find: Unknown regular expression type `foo'; valid types are `findutils-default', `awk', `egrep', `ed', `emacs', `gnu-awk', `grep', `posix-awk', `posix-basic', `posix-egrep', `posix-extended', `posix-minimal-basic', `sed'.

Solution 2 - Regex

The -regex find expression matches the whole name, including the relative path from the current directory. For find . this always starts with ./, then any directories.

Also, these are emacs regular expressions, which have other escaping rules than the usual egrep regular expressions.

If these are all directly in the current directory, then

find . -regex '\./[a-f0-9\-]\{36\}\.jpg'

should work. (I'm not really sure - I can't get the counted repetition to work here.) You can switch to egrep expressions by -regextype posix-egrep:

find . -regextype posix-egrep -regex '\./[a-f0-9\-]{36}\.jpg'

(Note that everything said here is for GNU find, I don't know anything about the BSD one which is also the default on Mac.)

Solution 3 - Regex

Judging from other answers, it seems this might be find's fault.

However you can do it this way instead:

find . * | grep -P "[a-f0-9\-]{36}\.jpg"

You might have to tweak the grep a bit and use different options depending on what you want but it works.

Solution 4 - Regex

on Mac OS X (BSD find): Same effect as the accepted answer.

$ find -E . -regex ".*/[a-f0-9\-]{36}.jpg"

man find says -E uses extended regex support

NOTE: the .*/ prefix is needed to match a complete path:

For comparison purposes, here's the GNU/Linux version:

$ find . -regextype sed -regex ".*/[a-f0-9\-]\{36\}\.jpg"

Solution 5 - Regex

Simple way - you can specify .* in the beginning because find matches the whole path.

$ find . -regextype egrep -regex '.*[a-f0-9\-]{36}\.jpg$'

find version

$ find --version
find (GNU findutils) 4.6.0
Copyright (C) 2015 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
<http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Eric B. Decker, James Youngman, and Kevin Dalley.
Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION 
FTS(FTS_CWDFD) CBO(level=2)

Solution 6 - Regex

Try to use single quotes (') to avoid shell escaping of your string. Remember that the expression needs to match the whole path, i.e. needs to look like:

 find . -regex '\./[a-f0-9-]*.jpg'

Apart from that, it seems that my find (GNU 4.4.2) only knows basic regular expressions, especially not the {36} syntax. I think you'll have to make do without it.

Solution 7 - Regex

You should use absolute directory path when applying find instruction with regular expression. In your example, the

find . -regex "[a-f0-9\-]\{36\}\.jpg"

should be changed into

find . -regex "./[a-f0-9\-]\{36\}\.jpg"

In most Linux systems, some disciplines in regular expression cannot be recognized by that system, so you have to explicitly point out -regexty like

find . -regextype posix-extended -regex "[a-f0-9\-]\{36\}\.jpg"

Solution 8 - Regex

If you want to maintain cross-platform compatibility, I could find no built-in regex search option that works across different versions of find in a consistent way.

Combine with grep

  1. As suggested by @yarian, you could run an over-inclusive find and then run the output through grep:

find . | grep -E '<POSIX regex>'

This is likely to be slow but will give you cross-platform regex search if you need to use a full regular expression and can't reformat your search as a glob

Rewrite as a glob

  1. The -name option is compatible with globs which will provide limited (but cross-platform) pattern matching.

You can use all the patterns that you would on the command line like * ? {} **. Although not as powerful as full regex, you might be able to reformulate your search to globs depending on your use-case.

Internet search for globs - many tutorials detailing full functionality are available online

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionthoslinView Question on Stackoverflow
Solution 1 - RegexSusam PalView Answer on Stackoverflow
Solution 2 - RegexPaŭlo EbermannView Answer on Stackoverflow
Solution 3 - RegexyarianView Answer on Stackoverflow
Solution 4 - RegexStan KurdzielView Answer on Stackoverflow
Solution 5 - RegexbinbjzView Answer on Stackoverflow
Solution 6 - RegexthitonView Answer on Stackoverflow
Solution 7 - RegexLovelyView Answer on Stackoverflow
Solution 8 - RegexMarkView Answer on Stackoverflow