I'm trying to use the result of ls
in other commands (e.g. echo, rsync):
all:
<Building, creating some .tgz files - removed for clarity>
FILES = $(shell ls)
echo $(FILES)
But I get:
make
FILES = Makefile file1.tgz file2.tgz file3.tgz
make: FILES: No such file or directory
make: *** [all] Error 1
I've tried using echo $$FILES
, echo ${FILES}
and echo $(FILES)
, with no luck.
With:
indented underneath
all
like that, it's a build command. So this expands$(shell ls)
, then tries to run the commandFILES ...
.If
FILES
is supposed to be amake
variable, these variables need to be assigned outside the recipe portion, e.g.:Of course, that means that
FILES
will be set to "output fromls
" before running any of the commands that create the .tgz files. (Though as Kaz notes the variable is re-expanded each time, so eventually it will include the .tgz files; some make variants haveFILES := ...
to avoid this, for efficiency and/or correctness.1)If
FILES
is supposed to be a shell variable, you can set it but you need to do it in shell-ese, with no spaces, and quoted:However, each line is run by a separate shell, so this variable will not survive to the next line, so you must then use it immediately:
This is all a bit silly since the shell will expand
*
(and other shell glob expressions) for you in the first place, so you can just:as your shell command.
Finally, as a general rule (not really applicable to this example): as esperanto notes in comments, using the output from
ls
is not completely reliable (some details depend on file names and sometimes even the version ofls
; some versions ofls
attempt to sanitize output in some cases). Thus, as l0b0 and idelic note, if you're using GNU make you can use$(wildcard)
and$(subst ...)
to accomplish everything insidemake
itself (avoiding any "weird characters in file name" issues). (Insh
scripts, including the recipe portion of makefiles, another method is to usefind ... -print0 | xargs -0
to avoid tripping over blanks, newlines, control characters, and so on.)1The GNU Make documentation notes further that POSIX make added
::=
assignment in 2012. I have not found a quick reference link to a POSIX document for this, nor do I know off-hand whichmake
variants support::=
assignment, although GNU make does today, with the same meaning as:=
, i.e., do the assignment right now with expansion.Note that
VAR := $(shell command args...)
can also be spelledVAR != command args...
in severalmake
variants, including all modern GNU and BSD variants as far as I know. These other variants do not have$(shell)
so usingVAR != command args...
is superior in both being shorter and working in more variants.Also, in addition to torek's answer: one thing that stands out is that you're using a lazily-evaluated macro assignment.
If you're on GNU Make, use the
:=
assignment instead of=
. This assignment causes the right hand side to be expanded immediately, and stored in the left hand variable.If you use the
=
assignment, it means that every single occurrence of$(FILES)
will be expanding the$(shell ...)
syntax and thus invoking the shell command. This will make your make job run slower, or even have some surprising consequences.