Bash extended globbing inside a Makefile

I want to do an operation on all the files in a particular folder that do not start with a particular prefix (say exclude_). I have a bash for loop with an extended glob that looks like this:

for FILE in foo/bar/!(exclude_*) ; do echo $FILE ; done

On the command line, this works fine:

 $ for FILE in foo/bar/!(exclude_*) ; do echo $FILE ; done
 foo/bar/apple
 foo/bar/pear
 foo/bar/banana

But, when I use it in a makefile:

target:
    for FILE in foo/bar/!(exclude_*) ; do echo $$FILE ; done

I get the following error:

$ make
for FILE in foo/bar/!(exclude_*) ; do echo $FILE ; done
/bin/sh: -c: line 0: syntax error near unexpected token `('
/bin/sh: -c: line 0: `for FILE in foo/bar/!(exclude_*) ; do echo $FILE ; done'

Is there some necessary escaping that I've missed?


  1. You need to set extglob.
  2. You need to tell make to use bash, not sh.

Makefile:

SHELL=/bin/bash
.SHELLFLAGS="-O extglob -c"
 ...

It would be more idiomatic and more portable to solve this with Make and not with Bash hacks. What if someone doesn't have Bash installed?

Anyway, here's the proper way to do it in Make:

FOOFILES = $(filter-out foo/bar/exclude_%,$(wildcard foo/bar/*))

target:
    for FILE in ${FOOFILES}; do echo $$FILE ; done

Here is a simpler way:

SHELL:=/bin/bash -O globstar

which will enable globstar shell option (which works on BSD/OS X as well).