Use of the "OR" Regex operator with the find command

There are so many of these questions on the net, but I was unable to solve this simple problem.

I have a directory with a lot of images, but I only want to copy a subset of them identified by ranges of numbers. Each picture has the format: "[random characters][capture number].BMP"

For example: IZ000561.BMP

I am using this in conjunction with find and the -regex option. The regular expression I thought to use was simple:

.*(26[2-7]|27[0-2]).*

if I wanted to match images with a tag of [262-267],[270-272]. This approach failed, however. I went to an online Regex tester and all matched as expected using this expression. It must be that find's regex engine expects a different format for this kind of filtering.

The full command I was using:

find /path/to/images/ -regex ".*(26[2-7]|27[0-2]).*" -exec echo {} \;

What is a valid expression for what I am trying to do?

3 Answers

Reading into the man page of find gives a bit of useful information:

The regular expressions understood by find are by default Emacs Regular Expressions.

So, taking a look into the syntax of Emacs Regex

enter image description here

It seems that all special characters are required to be escaped with \. Taking this into account, the expected results were obtained after changing the regular expression to the following:

find /path/to/images/ -regex ".*\(26[2-7]\|27[0-2]\).*" -exec echo {} \;

I consulted the man page before posting this question, but apparently not meticulously enough.

I realise you posted your own answer, but in case you wish to use the REGEX syntax you are, you can change the REGEX type using this command:

-regextype TYPE

So I believe to make yours work:

find /path/to/images/ -regextype sed -regex '.*(26[2-7]|27[0-2]).*' -exec echo {} \;

may do the trick.

Also, just a note, your regex will match anything with 262-267 or 270-272 within. That means it'll catch IZ262561.BMP, as well as IZ134267.JPG, and ASDNASDNOANFOIAJFOIJDIO000262.EXE for example. I'm not sure what files you're working with, but you might need to narrow your regex down as it's quite loose on what it'll accept.

2

There also is an -or (or -o) operator to the find command. You could divide your expression in two subexpressions:

find /path/to/images/ -regex ".*(26[2-7]).*" -o -regex ".*(27[0-2]).*" -exec echo {} \;

-o is POSIX compliant, while -or is not:

As per the find man page:

 expr1 -o expr2 Or; expr2 is not evaluated if expr1 is true. expr1 -or expr2 Same as expr1 -o expr2, but not POSIX compliant.
1

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like