Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why isn't this regex working : find ./ -regex '.*\(m\|h\)$

Tags:

regex

macos

Why isn't this regex working?

  find ./ -regex '.*\(m\|h\)$

I noticed that the following works fine:

  find ./ -regex '.*\(m\)$'

But when I add the "or a h at the end of the filename" by adding \|h it doesn't work. That is, it should pick up all my *.m and *.h files, but I am getting nothing back.

I am on Mac OS X.

like image 450
Greg Avatar asked May 06 '11 00:05

Greg


4 Answers

On Mac OS X, you can't use \| in a basic regular expression, which is what find uses by default.

re_format man page

[basic] regular expressions differ in several respects. | is an ordinary character and there is no equivalent for its functionality.

The easiest fix in this case is to change \(m\|h\) to [mh], e.g.

find ./ -regex '.*[mh]$'

Or you could add the -E option to tell find to use extended regular expressions instead.

find -E ./ -regex '.*(m|h)$'

Unfortunately -E isn't portable.

Also note that if you only want to list files ending in .m or .h, you have to escape the dot, e.g.

find ./ -regex '.*\.[mh]$'

If you find this confusing (me too), there's a great reference table that shows which features are supported on which systems.

Regex Syntax Summary [Google Cache]

like image 86
Mikel Avatar answered Nov 20 '22 15:11

Mikel


A more efficient solution is to use the -o flag:

find . -type f \( -name "*.m" -o -name "*.h" \)

but if you want the regex use:

find . -type f -regex ".*\.[mh]$"
like image 40
Wes Avatar answered Nov 20 '22 16:11

Wes


Okay this is a little hacky but if you don't want to wrangle the regex limitations of find on OSX, you can just pipe find's output to grep:

find . | grep ".*\(\h\|m\)"
like image 3
IDBUYTHATFORADOLLAR Avatar answered Nov 20 '22 16:11

IDBUYTHATFORADOLLAR


What’s wrong with

find . -name '*.[mh]' -type f

If you want fancy patterns, then use find2perl and hack the pattern.

like image 1
tchrist Avatar answered Nov 20 '22 16:11

tchrist