4

I am attempting to run this find command to match files with a camelcased name, with the goal being to put a space between adjacent lower and upper case letters, but it's not matching anything:

find -E . -regex "([a-z])([A-Z])"

An example of a file I'm trying to match is

./250 - ErosPhiliaAgape.mp3

I've tested this regex on this file here and it matches successfully.

What is it I'm doing wrong with my find command?

  • What operating system are you using? The -E is not a standard option. – terdon Dec 23 '16 at 16:06
  • Mac OS. The -E is for extended regex. – user206934 Dec 23 '16 at 16:07
  • 1
    Yeah, I found it. In future, please remember to always mention your OS. GNU find (Linux) is not the same as BSD find (OSX) which is not the same as POSIX find`. Many of the standard tools behave differently in different *nix systems. – terdon Dec 23 '16 at 16:14
4

You're probably looking for something like:

find . -name "*[a-z][A-Z]*"
  • That works, but when I place the matched characters in a capture group like so "([a-z])([A-Z])" it doesn't match. – user206934 Dec 23 '16 at 15:31
  • 1
    Find won't handle capture groups. See unix.stackexchange.com/questions/139331/… – SYN Dec 23 '16 at 15:34
  • @ChrisWilson that's because the regex needs to match the entire path. The -name does not take regular expressions, it takes globs, and that only needs top match the name. – terdon Dec 23 '16 at 16:32
  • @SYN actually, as I just learned, GNU find can handle capture groups. Dunno about BSD/OSX find. In fact, that is very nicely demonstrated in the accepted answer to the question you linked to. – terdon Dec 23 '16 at 16:34
3

Find's -regex matches the entire path, not just the file name. That means that to find /path/to/foo, you need -regex'.*foo', and not justfoo`. You want something like:

find  . -E -regex ".*[a-z][A-Z].*"

It would be much simpler to use globs and the simpler -name as suggested by SYN, however, instead of regexes.

  • @steeldriver wow. That's completely new to me, thanks! – terdon Dec 23 '16 at 16:29
1

This happens because ([a-z])([A-Z]) does not match ./250 - ErosPhiliaAgape.mp3. In fact, ([a-z])([A-Z]) can only match exactly 2 characters -- -regex is an anchored match over the entire path. If you want to use -regex to search for a file whose name contains a regex, you can write it like this (BSD/macOS find syntax):

find -E . -regex '.*/[^/]*([a-z])([A-Z])[^/]*'

The GNU find equivalent would be something like

find . -regextype posix-extended -regex '.*/[^/]*([a-z])([A-Z])[^/]*'