22

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?

4 Answers 4

13
  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"
 ...
8
  • 3
    Hmm. For some reason the .SHELLFLAGS didn't work for me, but putting the flags directly in SHELL=/bin/bash -O extglob -c did. Any ideas why? Jul 15, 2013 at 6:01
  • 1
    Maybe you're not using GNU make. Or maybe it doesn't need the quotes. Jul 15, 2013 at 6:01
  • GNU Make 3.81, and GNU bash, version 4.1.2. Tried without the quotes too. Weird. Jul 15, 2013 at 6:02
  • 1
    Anyway, your answer solved it for me once I put them all on the one line. Thanks! Jul 15, 2013 at 6:03
  • 1
    The .SHELLFLAGS variable was added in GNU make 3.82. You can check which features were added in which releases via the NEWS file: git.savannah.gnu.org/cgit/make.git/tree/NEWS Feb 12, 2017 at 17:06
13

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
0
4

Here is a simpler way:

SHELL:=/bin/bash -O globstar

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

0
0

Add this to the top of the Makefile:

SHELL := bash -O extglob
1
  • 1
    Doesn't work. The above version is correct.
    – Desik
    Sep 21, 2018 at 7:22

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .