Com:
FILES = $(shell ls)
recuado embaixo all
assim, é um comando de construção. Portanto, isso se expande e $(shell ls)
, em seguida, tenta executar o comando FILES ...
.
Se FILES
é suposto ser uma make
variável, essas variáveis precisam ser atribuídas fora da parte da receita, por exemplo:
FILES = $(shell ls)
all:
echo $(FILES)
Claro, isso significa que FILES
será definido como "saída de ls
" antes de executar qualquer um dos comandos que criam os arquivos .tgz. (Embora, como Kaz observa, a variável seja expandida novamente a cada vez, então eventualmente ela incluirá os arquivos .tgz; algumas variantes de criação devem FILES := ...
evitar isso, para eficiência e / ou correção. 1 )
Se FILES
deveria ser uma variável shell, você pode defini-la, mas precisa fazer isso em shell-ese, sem espaços e entre aspas:
all:
FILES="$(shell ls)"
No entanto, cada linha é executada por um shell separado, então essa variável não sobreviverá à próxima linha, então você deve usá-la imediatamente:
FILES="$(shell ls)"; echo $$FILES
Isso tudo é um pouco bobo, pois o shell se expandirá *
(e outras expressões do shell glob) para você em primeiro lugar, então você pode apenas:
echo *
como seu comando shell.
Finalmente, como regra geral (não se aplica realmente a este exemplo): como as notas do esperanto nos comentários, usar a saída de ls
não é totalmente confiável (alguns detalhes dependem dos nomes dos arquivos e às vezes até da versão de ls
; algumas versões de ls
tentativa de sanitizar a saída em alguns casos). Assim, como 10b0 e idelic note, se você estiver usando GNU make você pode usar $(wildcard)
e $(subst ...)
realizar tudo dentro de make
si (evitando quaisquer problemas de "caracteres estranhos no nome do arquivo"). (Em sh
scripts, incluindo a parte da receita de makefiles, outro método é usar find ... -print0 | xargs -0
para evitar tropeçar em espaços em branco, novas linhas, caracteres de controle e assim por diante.)
1 O GNU Make documenta ainda que POSIX fez ::=
atribuições adicionais em 2012 . Não encontrei um link de referência rápida para um documento POSIX para isso, nem sei de antemão quais make
variantes suportam ::=
atribuição, embora o GNU faça hoje, com o mesmo significado que :=
, ou seja, fazer a atribuição agora com expansão.
Observe que VAR := $(shell command args...)
também pode ser escrito VAR != command args...
em várias make
variantes, incluindo todas as variantes modernas do GNU e do BSD, até onde eu sei. Essas outras variantes não têm, $(shell)
portanto, o uso VAR != command args...
é superior por ser mais curto e funcionar em mais variantes.
ls
comsed
e cortar, por exemplo) e depois usar os resultados em rsync e outros comandos. Eu tenho que repetir o comando longo indefinidamente? Não posso armazenar os resultados em uma variável interna Make?FILE = $(shell ls *.c | sed -e "s^fun^bun^g")
make
pode fazer isso sem usar o shell:FILE = $(subst fun,bun,$(wildcard *.c))
.Além disso, além da resposta de torek: uma coisa que se destaca é que você está usando uma atribuição de macro avaliada vagarosamente.
Se você estiver no GNU Make, use a
:=
atribuição em vez de=
. Esta atribuição faz com que o lado direito seja expandido imediatamente e armazenado na variável do lado esquerdo.Se você usar a
=
atribuição, significa que cada ocorrência de$(FILES)
estará expandindo a$(shell ...)
sintaxe e, portanto, invocando o comando shell. Isso fará com que seu trabalho seja mais lento ou até mesmo terá algumas consequências surpreendentes.fonte
for x in $(FILES); do command $$x; done
. Observe o dobrado$$
que passa um único$
para o shell. Além disso, os fragmentos de casca são de uma linha; para escrever código de shell de várias linhas, você usa a continuação de barra invertida que é processada pormake
si mesma e dobrada em uma linha. O que significa que os pontos-e-vírgulas separadores de comandos do shell são obrigatórios.