Bash ha esteso il movimento all'interno di un Makefile


14

Voglio fare un'operazione su tutti i file in una cartella particolare che non iniziano con un prefisso particolare (diciamo exclude_). Ho un forloop bash con un glob esteso che assomiglia a questo:

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

Sulla riga di comando, funziona perfettamente:

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

Ma quando lo uso in un makefile:

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

Ottengo il seguente errore:

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

C'è qualche evasione necessaria che mi è sfuggita?

Risposte:


6
  1. Devi impostare extglob.
  2. Devi dire a make di usare bash, non sh.

Makefile:

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

2
Hmm. Per qualche motivo .SHELLFLAGSnon ha funzionato per me, ma ha messo le bandiere direttamente dentro SHELL=/bin/bash -O extglob -c. Qualche idea sul perché?
Timothy Jones,

1
Forse non stai usando GNU make. O forse non ha bisogno delle virgolette.
Ignacio Vazquez-Abrams,

GNU Make 3.81 e GNU bash, versione 4.1.2. Ho provato anche senza le virgolette. Strano.
Timothy Jones,

Comunque, la tua risposta mi ha risolto una volta che li ho messi tutti su una riga. Grazie!
Timothy Jones,

1
La .SHELLFLAGSvariabile è stata aggiunta in GNU make 3.82. Puoi controllare quali funzionalità sono state aggiunte in quali versioni tramite il file NEWS: git.savannah.gnu.org/cgit/make.git/tree/NEWS
MadScientist,

11

Sarebbe più idiomatico e più portatile risolverlo con Make e non con gli hack di Bash. E se qualcuno non ha installato Bash?

Ad ogni modo, ecco il modo corretto di farlo in Make:

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

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

2

Ecco un modo più semplice:

SHELL:=/bin/bash -O globstar

che abiliterà l'opzione shell globstar (che funziona anche su BSD / OS X).


0

Aggiungi questo all'inizio del Makefile:

SHELL := bash -O extglob

1
Non funziona La versione precedente è corretta.
Desik,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.