2

On my Mac running Yosemite I have a directory of files on my Desktop:

29_foo10.bar
29_foo2.bar
29_foo20.bar
29_foo3.bar

I want to target the files with a single digit after foo. When I use find -name I can target the selection of files with:

USERNAME=darthvader
DIRECTORY="/Users/$USERNAME/desktop/test"
for theProblem in $(find $DIRECTORY -type f -name '29_foo[0-9].bar'); do
    cd $DIRECTORY
    echo $theProblem
done

and I'm returned the two files in the terminal (29_foo2.bar & 29_foo3.bar) but when I try using -regex it returns nothing, code:

for theProblem in $(find $DIRECTORY -type f -regex '29_foo[0-9].bar'); do
    cd $DIRECTORY
    echo $theProblem
done

I did some research and found OS X Find in bash with regex digits \d not producing expected results

so I modified my code to:

for theProblem in $(find -E $DIRECTORY -iregex '29_foo[0-9].bar'); do

and I'm returned:

No such file or directory

so I tried:

for theProblem in $(find -E $DIRECTORY -type f -regex '29_foo[0-9].bar'); do

but I still get:

No such file or directory

So I did some further research and found bash: recursively find all files that match a certain pattern and tested:

for theProblem in $(find $DIRECTORY -regex '29_foo[0-9].bar'); do

and I'm returned:

No such file or directory

Further down the rabbit hole I found How to use regex in file find so I tried:

for theProblem in $(find $DIRECTORY -regextype posix-extended -regex '29_foo[0-9].bar'); do

and terminal tells me:

find: -regextype: unknown primary or operator

Why in Yosemite am I not able to target the files with -regex? When I do man regex I am returned the manual, my bash version is 3.2.57. So why does -name work when -regex will not?

Community
  • 1
  • 1
DᴀʀᴛʜVᴀᴅᴇʀ
  • 7,681
  • 17
  • 73
  • 127
  • 1
    Note some of the solutions you found do work on [GNU find](http://linux.die.net/man/1/find), while your [OSX find](https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/find.1.html) misses some of the options like `-regextype`. – fedorqui Aug 29 '16 at 14:21
  • @fedorqui are you aware of any documentation that notes what is missing between GNU and OSX? – DᴀʀᴛʜVᴀᴅᴇʀ Aug 29 '16 at 14:23
  • 1
    Mmm no :/ And I wish there was one. – fedorqui Aug 29 '16 at 14:26
  • 1
    Familiarize yourself with the [POSIX specification for `find`](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/find.html). When trying to write portable code, it's more useful to be aware of what features are *extensions* to your particular version, rather than to think of what is *missing* from another version. – chepner Aug 29 '16 at 15:12

1 Answers1

2

You should use this regex in find:

find "$DIRECTORY" -type f -regex '.*/29_foo[0-9]\.bar$'

Changes are:

  • .*/ is required at start because there will be either a DOT or some directory path before each filename.
  • Added anchor $ in the end to avoid matching 29_foo3.barn if at all this filename is also there.
  • DOT needs to be escaped in -regex otherwise it will match any character.
  • Above find command will work on OSX-find as well on gnu-find.
anubhava
  • 761,203
  • 64
  • 569
  • 643
  • excellent and it works. To clarify, since I did see you edited but is it standard practice to always use `.*/` when calling on `-regex` and the DOT will always need to be escaped and it's not optional? – DᴀʀᴛʜVᴀᴅᴇʀ Aug 29 '16 at 14:33
  • DOT should be escaped as a good practice in regex otherwise it will also match a filename `29_foo2_bar`. `.*/` before your regex is definitely required since `-regex` is matching against full path of file starting from base path `"$DIRECTORY"`. – anubhava Aug 29 '16 at 14:47