Bash étendu globbing dans un Makefile

14

Je veux faire une opération sur tous les fichiers d'un dossier particulier qui ne commencent pas par un préfixe particulier (disons exclude_). J'ai une forboucle bash avec un glob étendu qui ressemble à ceci:

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

Sur la ligne de commande, cela fonctionne bien:

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

Mais, quand je l'utilise dans un makefile:

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

J'obtiens l'erreur suivante:

$ 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'

Y a-t-il des évasions nécessaires que j'ai ratées?

Timothy Jones
la source

Réponses:

6
  1. Vous devez régler extglob.
  2. Vous devez dire à make d'utiliser bash, pas sh.

Makefile:

SHELL=/bin/bash
.SHELLFLAGS="-O extglob -c"
 ...
Ignacio Vazquez-Abrams
la source
2
Hmm. Pour une raison quelconque, cela .SHELLFLAGSn'a pas fonctionné pour moi, mais mettre les drapeaux directement SHELL=/bin/bash -O extglob -ca fonctionné. Des idées pourquoi?
Timothy Jones
1
Peut-être que vous n'utilisez pas GNU make. Ou peut-être qu'il n'a pas besoin des guillemets.
Ignacio Vazquez-Abrams
GNU Make 3.81 et GNU bash, version 4.1.2. Essayé sans les citations aussi. Bizarre.
Timothy Jones
Quoi qu'il en soit, votre réponse l'a résolu pour moi une fois que je les ai tous mis sur la même ligne. Merci!
Timothy Jones
1
La .SHELLFLAGSvariable a été ajoutée dans GNU make 3.82. Vous pouvez vérifier quelles fonctionnalités ont été ajoutées dans quelles versions via le fichier NEWS: git.savannah.gnu.org/cgit/make.git/tree/NEWS
MadScientist
11

Il serait plus idiomatique et plus portable de résoudre ce problème avec Make et pas avec les hacks Bash. Et si quelqu'un n'a pas installé Bash?

Quoi qu'il en soit, voici la bonne façon de le faire dans Make:

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

target:
    for FILE in ${FOOFILES}; do echo $$FILE ; done
Timothy Jones
la source
2

Voici une manière plus simple:

SHELL:=/bin/bash -O globstar

qui activera l'option shell globstar (qui fonctionne également sur BSD / OS X).

Kenorb
la source
0

Ajoutez ceci en haut du Makefile:

SHELL := bash -O extglob
Geremia
la source
1
Ça ne marche pas. La version ci-dessus est correcte.
Desik