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?

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"
 ...

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

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).


0

Ajoutez ceci en haut du Makefile:

SHELL := bash -O extglob

1
Ça ne marche pas. La version ci-dessus est correcte.
Desik
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.