How to use shell commands in Makefile
bash, echo, makefile
Solution
With:
FILES = $(shell ls)
indented underneath `all` like that, it's a build command. So this expands `$(shell ls)`, then tries to run the command `FILES ...`.
If `FILES` is supposed to be a `make` variable, these variables need to be assigned outside the recipe portion, e.g.:
FILES = $(shell ls)
all:
echo $(FILES)
Of course, that means that `FILES` will be set to "output from `ls`" 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 have `FILES := ...` 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:
all:
FILES="$(shell ls)"
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:
FILES="$(shell ls)"; echo $$FILES
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:
echo *
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 of `ls`; some versions of `ls` 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 inside `make` itself (avoiding any "weird characters in file name" issues). (In `sh` scripts, including the recipe portion of makefiles, another method is to use `find ... -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 which `make` 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 spelled `VAR != command args...` in several `make` variants, including all modern GNU and BSD variants as far as I know. These other variants do not have `$(shell)` so using `VAR != command args...` is superior in both being shorter and working in more variants.
Problem
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.