simple loop over files in some directory makefile

Viewed 34444

I can easily print all the files inside some directory from bash:

$ cat go.sh
BASEDIR=~/Downloads
MYDIR=${BASEDIR}/ddd
for f in $(ls ${MYDIR}); do echo $f; done

$ ./go.sh
m.txt
d.txt

When I try to do a similar thing from makefile it doesn't work well:

$ cat makefile
BASEDIR = ${HOME}/Downloads
MYDIR = ${BASEDIR}/ddd
all:
    for f in $(ls ${MYDIR}); do echo ${f}; done

$ make
for f in ; do echo ; done

And here is another trial that doesn't work:

$ cat makefile
BASEDIR = ${HOME}/Downloads
MYDIR = ${BASEDIR}/ddd
all:
    for f in $(shell ls ${MYDIR}); do echo ${f}; done

$ make
for f in d.txt m.txt; do echo ; done
4 Answers

Maybe you can do it purely Makefile way?

MYDIR = .
list: $(MYDIR)/*
        @echo $^

You can still run command from Makefile like this

MYDIR = .
list: $(MYDIR)/*
        for file in $^ ; do \
                echo "Hello" $${file} ; \
        done

If I were you, I'd rather not mix Makefile and bash loops based on $(shell ...). I'd rather pass dir name to some script and run loop there - inside script.

Also almost "true way" from documentation

TEMPLATES_DIR = ./somedir

list: 
    $(foreach file, $(wildcard $(TEMPLATES_DIR)/*), echo $(file);)

Here is the edited answer based on @Oo.oO:

$ cat makefile
BASEDIR = ${HOME}/Downloads
MYDIR = ${BASEDIR}/ddd
all:
    @for f in $(shell ls ${MYDIR}); do echo $${f}; done

$ make
d.txt
m.txt

There is a little problem with @Oo.oO's answer.

If there is any file/folder has the same name with a target in makefile, and that target has some prerequisites, and you want to loop through that folder, you will get that target recipe being executed.

For example: if you have a folder named build, and you have a rule like:

build: clean server client

clean:
    @echo project cleaned!
server:
    @echo server built!
client:
    @echo client built!

To loop through the folder contains that special build folder, let's says you have the following rules:

MYDIR = .
ls: $(MYDIR)/*
    @echo $^

The result will be:

$ make ls
project cleaned!
server built!
client built!
build Makefile

I would suggest to use @Mike Pylypyshyn's solution. According to the make documentation, the foreach function is more suitable in this case.

Related