Bash rozszerzył globowanie w pliku Makefile

15

Chcę wykonać operację na wszystkich plikach w określonym folderze, które nie zaczynają się od określonego prefiksu (powiedzmy exclude_). Mam forpętlę bash z rozszerzoną glob, która wygląda następująco:

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

W wierszu poleceń działa to dobrze:

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

Ale kiedy używam go w makefile:

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

Otrzymuję następujący błąd:

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

Czy jest jakaś niezbędna ucieczka, za którą tęskniłem?

Timothy Jones
źródło

Odpowiedzi:

7
  1. Musisz ustawić extglob.
  2. Musisz powiedzieć make używać bash, a nie sh.

Makefile:

SHELL=/bin/bash
.SHELLFLAGS="-O extglob -c"
 ...
Ignacio Vazquez-Abrams
źródło
2
Hmm Z jakiegoś powodu .SHELLFLAGSnie zadziałało to dla mnie, ale bezpośrednie włożenie flag SHELL=/bin/bash -O extglob -c. Jakieś pomysły dlaczego?
Timothy Jones
1
Może nie używasz GNU make. A może nie potrzebuje cytatów.
Ignacio Vazquez-Abrams
GNU Make 3.81 i GNU bash, wersja 4.1.2. Próbowałem też bez cytatów. Dziwne.
Timothy Jones
W każdym razie twoja odpowiedź rozwiązała dla mnie, kiedy umieściłem je wszystkie w jednym wierszu. Dzięki!
Timothy Jones
1
.SHELLFLAGSZmienna dodano GNU make 3,82. Możesz sprawdzić, które funkcje zostały dodane w których wydaniach za pomocą pliku NEWS: git.savannah.gnu.org/cgit/make.git/tree/NEWS
MadScientist
11

Bardziej idiomatyczne i przenośne byłoby rozwiązanie tego problemu za pomocą Make, a nie hacków Bash. Co jeśli ktoś nie ma zainstalowanego Bash?

W każdym razie oto właściwy sposób na zrobienie tego w Make:

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

target:
    for FILE in ${FOOFILES}; do echo $$FILE ; done
Timothy Jones
źródło
2

Oto prostszy sposób:

SHELL:=/bin/bash -O globstar

która włączy opcję powłoki globstar (która działa również na BSD / OS X).

kenorb
źródło
0

Dodaj to na górze pliku Makefile:

SHELL := bash -O extglob
Geremia
źródło
1
Nie działa Powyższa wersja jest poprawna.
Desik