Bash estendido globbing dentro de um Makefile

14

Eu quero fazer uma operação em todos os arquivos em uma pasta específica que não iniciam com um prefixo específico (digamos exclude_). Eu tenho um forloop bash com uma glob estendida que se parece com isso:

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

Na linha de comando, isso funciona bem:

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

Mas quando eu o uso em um makefile:

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

Estou tendo o erro a seguir:

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

Existe alguma fuga necessária que eu perdi?

Timothy Jones
fonte

Respostas:

6
  1. Você precisa definir extglob.
  2. Você precisa dizer ao make para usar o bash, não o sh.

Makefile:

SHELL=/bin/bash
.SHELLFLAGS="-O extglob -c"
 ...
Ignacio Vazquez-Abrams
fonte
2
Hmm. Por alguma razão, .SHELLFLAGSisso não funcionou para mim, mas colocar as bandeiras diretamente SHELL=/bin/bash -O extglob -cfuncionou. Alguma idéia do porquê?
Timothy Jones
1
Talvez você não esteja usando o GNU make. Ou talvez não precise das aspas.
Ignacio Vazquez-Abrams
GNU Make 3.81 e GNU bash, versão 4.1.2. Tentei sem as aspas também. Esquisito.
Timothy Jones
De qualquer forma, sua resposta resolveu isso para mim quando eu os coloquei na mesma linha. Obrigado!
Timothy Jones
1
A .SHELLFLAGSvariável foi adicionada no GNU make 3.82. Você pode verificar quais recursos foram adicionados em quais lançamentos através do arquivo NEWS: git.savannah.gnu.org/cgit/make.git/tree/NEWS
MadScientist
10

Seria mais idiomático e mais portátil resolver isso com o Make e não com o Bash hacks. E se alguém não tiver o Bash instalado?

De qualquer forma, aqui está a maneira correta de fazer isso no Make:

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

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

Aqui está uma maneira mais simples:

SHELL:=/bin/bash -O globstar

que ativará a opção de shell globstar (que também funciona no BSD / OS X).

kenorb
fonte
0

Adicione isso ao topo do Makefile:

SHELL := bash -O extglob
Geremia
fonte
1
Não funciona A versão acima está correta.
Desik 21/09