0

Whenever I do

for f in data/*; echo $f; done

from a terminal, it correctly outputs every path.

However, if I add the said line to a makefile, let's say

test:
    for f in data/*; echo $f; done

and then run make test, instead of outputting the files it always outputs an empty string. It does this a number of times equal to the number of files/directories in the directory so it seems to loop correctly.

Why is that?

Edit: I found that doing $$f instead of $f does the trick but malforms the output if, for example, I use time to time the command.

Edit #2: Here's an example of the time command:

from makefile: for f in data/ascending_order/*; do time echo $$f; done

data/ascending_order/01/
0.00user 0.00system 0:00.01elapsed 0%CPU (0avgtext+0avgdata 804maxresident)k
0inputs+0outputs (0major+232minor)pagefaults 0swaps

from terminal for f in data/ascending_order/*; do time echo $f; done

data/ascending_order/01

real    0m0.001s
user    0m0.000s
sys     0m0.000s
2

The first issue (echo $f) is due to escaping inside the Makefile, if you use $f then make will think you're referring to the make variable instead of the shell variable and it will expand that (to empty) which will get your shell to run a single echo with a blank line for every file. The solution is to escape the $ by doubling it, in other words, use $$f, in which case make will consume one of the $s and pass the shell a $f, which is what you want.


Regarding the second issue (format of time output), what you're seeing is the difference in output format between the bash built-in time and the external command /usr/bin/time.

make will run the commands in your Makefile by passing them to /bin/sh, which some Linux distributions (most notably Debian and Ubuntu) ship pointing to dash, which is a simpler shell that doesn't implement a built-in time and would end up invoking the external command in that case.

You can get the bash time output by telling make to execute the commands in your Makefile using bash, which you can do with this variable assignment in your Makefile:

SHELL = /bin/bash
  • 1
    Thanks a lot for the explanation. I've accepted your answer. – Mike Nov 12 '18 at 18:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.