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.