4

This question already has an answer here:

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?

marked as duplicate by Gilles find Dec 24 '16 at 23:35

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 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])[^/]*'