我要遍历文件列表,在执行命令之前在其各自的目录中执行cd
。
所以我想使用$(dir $(FILES))
函数来获取目录,但是似乎在for
循环中不能正常工作。
FILES=../dir1/file1 ../dir2/file2
.PHONY: all
all:
@for f in $(FILES); do \
echo $$f in $(dir $${f}) ; \
done
输出
../dir1/file1 in ./
../dir2/file2 in ./
$(dir $${f})
扩展为./
,而不是../dirN
。
注意:
echo $(dir $(FILES))
循环输出for
之外写入../dir1/ ../dir2/
。$(abspath ...)
也不起作用。我想念什么?
答案 0 :(得分:1)
您正在混合make构造(dir
)和shell构造。不幸的是,没有同时评估它们。 Make会在将配方传递给外壳之前 一次评估其构造,而不是在外壳执行配方期间进行评估。扩展配方时(在将其传递给外壳之前),它将转换为:
for f in ../dir1/file1 ../dir2/file2; do echo $f in ./; done
因为当make展开$(dir $${f})
时,它首先会扩展参数:
$(dir ${f})
,然后,由于字符串/
中没有${f}
,因此dir
函数的扩展将其替换为./
。从GNU make手册:
$(dir names…)
提取名称中每个文件名的目录部分。文件名的目录部分是所有内容(和 包括)中的最后一个斜杠。如果文件名不包含斜杠, 目录部分是字符串
./
。例如,$(dir src/foo.c hacks)
产生结果
src/ ./
。
无论如何,混合make和shell结构通常不是您想要做的(有例外)。您只能使用shell构造:
all:
$(FILES); do \
echo $$f in $$(dirname $$f) ; \
done
或者您可以使用static pattern rule完全摆脱shell循环,并使其遍历类似目标的列表:
FILES = ../dir1/file1 ../dir2/file2
FOOS = $(addsuffix .foo,$(FILES))
.PHONY: all $(FOOS)
all: $(FOOS)
$(FOOS): %.foo:
@echo $* in $(dir $*)