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?
- You need to set
extglob
. - 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).