Bash memperluas globbing di dalam Makefile

14

Saya ingin melakukan operasi pada semua file dalam folder tertentu yang tidak dimulai dengan awalan tertentu (katakanlah exclude_). Saya memiliki bash forloop dengan gumpalan diperpanjang yang terlihat seperti ini:

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

Di baris perintah, ini berfungsi dengan baik:

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

Tapi, ketika saya menggunakannya di makefile:

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

Saya mendapatkan kesalahan berikut:

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

Apakah ada beberapa pelarian yang perlu saya lewatkan?

Timothy Jones
sumber

Jawaban:

6
  1. Anda perlu mengatur extglob .
  2. Anda perlu memberitahu make untuk menggunakan bash, bukan sh.

Makefile:

SHELL=/bin/bash
.SHELLFLAGS="-O extglob -c"
 ...
Ignacio Vazquez-Abrams
sumber
2
Hmm. Untuk beberapa alasan, .SHELLFLAGSitu tidak berhasil untuk saya, tetapi menempatkan bendera secara langsung SHELL=/bin/bash -O extglob -c. Ada ide mengapa?
Timothy Jones
1
Mungkin Anda tidak menggunakan GNU make. Atau mungkin tidak perlu tanda kutip.
Ignacio Vazquez-Abrams
GNU Make 3.81, dan GNU bash, versi 4.1.2. Mencoba tanpa tanda kutip juga. Aneh.
Timothy Jones
Ngomong-ngomong, jawaban Anda menyelesaikannya untuk saya setelah saya menempatkan semuanya di satu baris. Terima kasih!
Timothy Jones
1
The .SHELLFLAGSvariabel ditambahkan dalam GNU make 3,82. Anda dapat memeriksa fitur mana yang ditambahkan di mana rilis melalui file NEWS: git.savannah.gnu.org/cgit/make.git/tree/NEWS
MadScientist
10

Akan lebih idiomatis dan lebih portabel untuk menyelesaikan ini dengan Make dan bukan dengan hack Bash. Bagaimana jika seseorang tidak menginstal Bash?

Bagaimanapun, inilah cara yang tepat untuk melakukannya di Make:

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

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

Ini cara yang lebih sederhana:

SHELL:=/bin/bash -O globstar

yang akan mengaktifkan opsi shell globstar (yang juga berfungsi pada BSD / OS X).

kenorb
sumber
0

Tambahkan ini ke bagian atas Makefile:

SHELL := bash -O extglob
Geremia
sumber
1
Tidak bekerja Versi di atas benar.
Desik