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?

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

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

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


0

Adicione isso ao topo do Makefile:

SHELL := bash -O extglob

1
Não funciona A versão acima está correta.
— Desik 21/09
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.