我想使用循环来查找一些文件并重命名它们:
for i in `find $@ -name *_cu.*`;do mv $i "$(echo $i|sed s/_cu//)"
done
这在外壳中有效。但是我怎样才能在 makefile 配方中做到这一点?
将重要的 shell 片段放入 make recipe 时,您需要了解两件主要的事情:
配方中的命令(当然!)一次执行一个,其中命令的意思是“配方中的制表符前缀行”,可能分布在带有反斜杠的多个 makefile 行中。
所以你的 shell 片段必须全部写在一个(可能是反斜杠)行上。此外,它作为单行有效地呈现给 shell(反斜杠换行符不是普通的换行符,因此 shell 不将其用作命令终止符),因此在语法上必须是正确的。
shell 变量和 make 变量都由美元符号 ( $@
, $i
) 引入,因此您需要将 shell 变量写为$$i
. (更准确地说,您希望 shell 看到的任何美元符号都必须通过将其写为 . 来从 make 中转义$$
。)
通常在 shell 脚本中,您会在不同的行上编写单独的命令,但在这里您实际上只能得到一行,因此必须用分号分隔各个 shell 命令。将所有这些放在您的示例中会产生:
foo: bar
for i in `find $@ -name *_cu.*`; do mv $$i "$$(echo $$i|sed s/_cu//)"; done
或等效地:
foo: bar
for i in `find $@ -name *_cu.*`; do \
mv $$i "$$(echo $$i|sed s/_cu//)"; \
done
请注意,后者,即使它以可读的方式排列在几行上,也需要同样小心地使用分号来保持 shell 的正常运行。
我发现这很有用,尝试使用 for 循环来构建多个文件:
PROGRAMS = foo bar other
.PHONY all
all: $(PROGRAMS)
$(PROGRAMS):
gcc -o $@ $@.c
它将foo.c、bar.c、other.c编译成foo bar其他可执行文件
我花了很多时间在这上面,终于让它工作了。我有一个简单的解决方案,使用 makefile 中可用于所有目标的全局变量,但是我不希望这样,所以我就是这样做的。
target:
$(eval test_cont=$(shell sh -c "docker ps | grep test" | awk '{print $$1}'))
for container in $(test_cont);do \
docker cp ssh/id_rsa.pub $${container}:/root/.ssh/authorized_keys; \
docker exec -it $${container} chown root.root /root/.ssh/authorized_keys; \
done