11

我想使用循环来查找一些文件并重命名它们:

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

这在外壳中有效。但是我怎样才能在 makefile 配方中做到这一点?

4

3 回答 3

34

将重要的 shell 片段放入 make recipe 时,您需要了解两件主要的事情:

  1. 配方中的命令(当然!)一次执行一个,其中命令的意思是“配方中的制表符前缀行”,可能分布在带有反斜杠的多个 makefile 行中。

    所以你的 shell 片段必须全部写在一个(可能是反斜杠)行上。此外,它作为单行有效地呈现给 shell(反斜杠换行符不是普通的换行符,因此 shell 不将其用作命令终止符),因此在语法上必须是正确的。

  2. 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 的正常运行。

于 2012-01-06T12:28:58.273 回答
5

我发现这很有用,尝试使用 for 循环来构建多个文件:

PROGRAMS = foo bar other

.PHONY all
all: $(PROGRAMS)
$(PROGRAMS):
    gcc -o $@ $@.c

它将foo.c、bar.c、other.c编译成foo bar其他可执行文件

于 2016-12-26T21:49:04.143 回答
0

我花了很多时间在这上面,终于让它工作了。我有一个简单的解决方案,使用 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
于 2021-10-07T20:12:11.223 回答