Con:
FILES = $(shell ls)
sangrado debajo all
así, es un comando de compilación. Entonces esto se expande $(shell ls)
, luego intenta ejecutar el comando FILES ...
.
Si FILES
se supone que es una make
variable, estas variables deben asignarse fuera de la parte de la receta, por ejemplo:
FILES = $(shell ls)
all:
echo $(FILES)
Por supuesto, eso significa que FILES
se configurará como "salida desde ls
" antes de ejecutar cualquiera de los comandos que crean los archivos .tgz. (Aunque, como señala Kaz, la variable se vuelve a expandir cada vez, por lo que eventualmente incluirá los archivos .tgz; algunas variantes de make tienen FILES := ...
que evitar esto, por eficiencia y / o corrección. 1 )
Si FILES
se supone que es una variable de shell, puede configurarlo, pero debe hacerlo en shell-ese, sin espacios y entre comillas:
all:
FILES="$(shell ls)"
Sin embargo, cada línea se ejecuta en un shell separado, por lo que esta variable no sobrevivirá a la siguiente línea, por lo que debe usarla inmediatamente:
FILES="$(shell ls)"; echo $$FILES
Todo esto es un poco tonto ya que el shell se expandirá *
(y otras expresiones de shell glob) para usted en primer lugar, por lo que puede simplemente:
echo *
como su comando de shell.
Finalmente, como regla general (no realmente aplicable a este ejemplo): como se observa en esperanto en los comentarios, usar la salida de ls
no es completamente confiable (algunos detalles dependen de los nombres de los archivos y, a veces, incluso de la versión de ls
; algunas versiones de ls
intento de desinfectar la salida en algunos casos). Por lo tanto, como nota l0b0 e idelic , si estás usando GNU make puedes usar $(wildcard)
y $(subst ...)
para lograr todo dentro de make
sí mismo (evitando cualquier problema de "caracteres extraños en el nombre del archivo"). (En los sh
scripts, incluida la parte de recetas de los archivos MAKE, se utiliza otro método find ... -print0 | xargs -0
para evitar tropezar con espacios en blanco, nuevas líneas, caracteres de control, etc.).
1 La documentación de GNU Make señala además que POSIX realiza una ::=
asignación adicional en 2012 . No he encontrado un enlace de referencia rápida a un documento POSIX para esto, ni sé de antemano qué make
variantes admiten la ::=
asignación, aunque GNU lo hace hoy, con el mismo significado que :=
, es decir, hacer la asignación ahora mismo con expansión.
Tenga en cuenta que VAR := $(shell command args...)
también se puede escribir VAR != command args...
en varias make
variantes, incluidas todas las variantes modernas de GNU y BSD que yo sepa. Estas otras variantes no tienen, $(shell)
por lo que su uso VAR != command args...
es superior tanto por ser más cortas como por trabajar en más variantes.
ls
consed
y cortar, por ejemplo) y luego usar los resultados en rsync y otros comandos. ¿Tengo que repetir el comando largo una y otra vez? ¿No puedo almacenar los resultados en una variable Make interna?FILE = $(shell ls *.c | sed -e "s^fun^bun^g")
make
puede hacer que sin utilizar el shell:FILE = $(subst fun,bun,$(wildcard *.c))
.Además, además de la respuesta de torek: una cosa que se destaca es que está utilizando una asignación de macro evaluada de forma perezosa.
Si está en GNU Make, use la
:=
asignación en lugar de=
. Esta asignación hace que el lado derecho se expanda inmediatamente y se almacene en la variable del lado izquierdo.Si usa la
=
asignación, significa que cada aparición de$(FILES)
expandirá la$(shell ...)
sintaxis y, por lo tanto, invocará el comando de shell. Esto hará que su trabajo de creación se ejecute más lento o incluso tendrá algunas consecuencias sorprendentes.fuente
for x in $(FILES); do command $$x; done
. Tenga en cuenta el doble$$
que pasa un sencillo$
al caparazón. Además, los fragmentos de concha son frases ingeniosas; para escribir código de shell de varias líneas, utiliza la continuación de la barra invertida que se procesa pormake
sí misma y se dobla en una línea. Lo que significa que los puntos y comas de separación de comandos de shell son obligatorios.