Dengan:
FILES = $(shell ls)
menjorok di bawahnya all
seperti itu, itu adalah perintah build. Jadi ini mengembang $(shell ls)
, lalu mencoba menjalankan perintahFILES ...
.
Jika FILES
seharusnya menjadi make
variabel, variabel ini perlu ditempatkan di luar bagian resep, misalnya:
FILES = $(shell ls)
all:
echo $(FILES)
Tentu saja, itu berarti FILES
akan disetel ke "keluaran dari ls
" sebelum menjalankan perintah apa pun yang membuat berkas .tgz. (Meskipun seperti yang dicatat Kaz , variabel tersebut diperluas kembali setiap kali, jadi pada akhirnya ia akan menyertakan file .tgz; beberapa varian make harus FILES := ...
menghindari ini, demi efisiensi dan / atau kebenaran. 1 )
Jika FILES
seharusnya menjadi variabel shell, Anda dapat mengaturnya tetapi Anda perlu melakukannya dalam shell-ese, tanpa spasi, dan dikutip:
all:
FILES="$(shell ls)"
Namun, setiap baris dijalankan oleh shell terpisah, jadi variabel ini tidak akan bertahan hingga baris berikutnya, jadi Anda harus segera menggunakannya:
FILES="$(shell ls)"; echo $$FILES
Ini semua agak konyol karena shell akan mengembang *
(dan ekspresi shell glob lainnya) untuk Anda sejak awal, jadi Anda bisa:
echo *
sebagai perintah shell Anda.
Akhirnya, sebagai aturan umum (tidak benar-benar berlaku untuk contoh ini): seperti catatan esperanto dalam komentar, menggunakan keluaran dari ls
tidak sepenuhnya dapat diandalkan (beberapa detail bergantung pada nama file dan terkadang bahkan versi ls
; beberapa versi ls
upaya untuk membersihkan keluaran dalam beberapa kasus). Jadi, sebagai l0b0 dan catatan idelic , jika Anda menggunakan GNU make, Anda dapat menggunakan $(wildcard)
dan $(subst ...)
menyelesaikan semua yang ada di dalamnya make
(menghindari masalah "karakter aneh dalam nama file"). (Dalam sh
skrip, termasuk bagian resep makefile, metode lain digunakan find ... -print0 | xargs -0
untuk menghindari tersandung kosong, baris baru, karakter kontrol, dan sebagainya.)
1 GNU Make mencatat lebih lanjut bahwa POSIX membuat ::=
tugas tambahan pada tahun 2012 . Saya belum menemukan tautan referensi cepat ke dokumen POSIX untuk ini, saya juga tidak tahu langsung make
varian mana yang mendukung ::=
penugasan, meskipun GNU membuat hari ini, dengan arti yang sama seperti :=
, yaitu, melakukan penugasan sekarang dengan perluasan.
Catatan itu VAR := $(shell command args...)
juga bisa dieja VAR != command args...
dalam beberapa make
varian, termasuk semua varian GNU dan BSD modern sejauh yang saya tahu. Varian lain ini tidak memiliki $(shell)
penggunaan sehingga VAR != command args...
lebih unggul baik karena lebih pendek dan bekerja di lebih banyak varian.
ls
dengansed
dan cut, misalnya) dan kemudian menggunakan hasilnya di rsync dan perintah lainnya. Apakah saya harus mengulangi perintah yang panjang itu berulang kali? Tidak dapatkah saya menyimpan hasil dalam variabel Make internal?FILE = $(shell ls *.c | sed -e "s^fun^bun^g")
make
bisa melakukan itu tanpa menggunakan shell:FILE = $(subst fun,bun,$(wildcard *.c))
.Selain itu, selain jawaban torek: satu hal yang menonjol adalah Anda menggunakan tugas makro yang dievaluasi secara malas.
Jika Anda menggunakan GNU Make, gunakan
:=
tugas sebagai ganti=
. Penugasan ini menyebabkan sisi kanan segera diperluas, dan disimpan di variabel kiri.Jika Anda menggunakan
=
penugasan, itu berarti bahwa setiap kemunculan$(FILES)
akan memperluas$(shell ...)
sintaks dan dengan demikian menjalankan perintah shell. Ini akan membuat pekerjaan Anda berjalan lebih lambat, atau bahkan memiliki beberapa konsekuensi yang mengejutkan.sumber
for x in $(FILES); do command $$x; done
. Perhatikan doubled up$$
yang mengirimkan satu$
ke shell. Selain itu, fragmen shell adalah satu baris; untuk menulis kode shell multi baris, anda menggunakan kontinuitas garis miring terbalik yang diproses denganmake
sendirinya dan dilipat menjadi satu baris. Yang berarti titik koma pemisah perintah shell bersifat wajib.