11

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 3

14

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.

7

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
  • +1 for the suggestion to make the expression more specific. The numbers are always followed by the .BMP extension, so that's a great way to do it. I noticed the argument to change the regex type, but there were no examples in the manual for using it, or valid types for use with this switch.Thanks!
    – sherrellbc
    Commented Jan 14, 2016 at 18:13
  • I tried typing in an incorrect parameter using the -regextype option and, sure enough, find reported the supported options as: findutils-default, awk, egrep, ed, emacs, gnu-awk, grep, posix-awk, posix-basic, posix-egrep, posix-extended, posix-minimal-basic, sed.
    – sherrellbc
    Commented Jan 14, 2016 at 18:25
6

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
  • Man, you totally saved me from a lot of headache. Thank you! Commented Feb 19, 2017 at 23:17

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .