How to use for loop in make recipe

I would like to use a loop to find some files and rename them:

for i in `find $@ -name *_cu.*`;do mv $i "$(echo $i|sed s/_cu//)" done 

This works in a shell. But how can I do this in a makefile recipe?

+7
source share
2 answers

There are two main things you need to know when to put nonzero shell fragments into recipes:

  • Commands in the recipe (of course!) Are executed one at a time, where the command means "a line with a tab prefix in the recipe", possibly spreading across several makefile lines with backslashes.

    So, your shell fragment should be written on one (possibly reverse) line. Moreover, it effectively represents the shell as a single line (backslashed-newlines are not simple newline characters, therefore they are not used as shell command terminators), and therefore should be syntactically correct as such.

  • Both shell variables and make variables are entered with dollar signs ( $@ , $i ), so you need to hide your shell variables from make by writing them as $$i . (More precisely, any dollar sign you want the shell to see must be escaped from make by writing it as $$ .)

Usually in a shell script, you should write separate commands in separate lines, but here you actually get only one line, so instead, separate shell commands should be semicolon. Combining all of this for your example, you get:

 foo: bar for i in `find $@ -name *_cu.*`; do mv $$i "$$(echo $$i|sed s/_cu//)"; done 

or equivalently:

 foo: bar for i in `find $@ -name *_cu.*`; do \ mv $$i "$$(echo $$i|sed s/_cu//)"; \ done 

Please note that the latter, although it is easy to read across multiple lines, requires the same careful use of semicolons to keep the shell happy.

+28
source

I found this useful when trying to use for loops to create multiple files:

 PROGRAMS = foo bar other .PHONY all all: $(PROGRAMS) $(PROGRAMS): gcc -o $@ $@.c 

It will compile foo.c, bar.c, other.c to foor bar other executables

0
source

All Articles