0

让我先写一个快速的 Makefile 作为展示:

#!/bin/make -f

folders := $(shell find -mindepth 1 -maxdepth 1 -type d -print)

make_dir:
    @mkdir -p "test0"

pwd_test:
    @cd "test0" && pwd
    @pwd

pwd_all:
    @for f in $(folders); do \
        cd "$${f}" && pwd; \
        pwd; \
        cd ..; \
    done

先做make make_dir然后看看不同的结果:

➜  so  make pwd_test
/data/cache/tmp/so/test0
/data/cache/tmp/so
➜  so  make pwd_all 
/data/cache/tmp/so/test0
/data/cache/tmp/so/test0

您会看到在 for 循环中必须执行cd ... 显然,现在该命令没有子进程生成cd X && pwd,而通常情况下是这样。这种行为是特定于制造还是特定于我的外壳?

4

1 回答 1

1

Make 为规则中的每个命令生成一个新进程。由于 for 循环是一个命令,因此您只能获得一个进程。

看看配方执行

编辑:

makefile 中的每一行都有它自己的子shell。有 \告诉的命令使下一行应该是当前行的一部分。

for 循环获得自己的子外壳的原因是因为 make 将行视为

@for f in $(folders); do cd "$${f}" && pwd; pwd; cd ..; done

MadScientist 很好地解释了这一点。您可以在一行中在 shell 中键入的任何命令都将由 make 在一个子 shell 或进程中执行。

如果你要在 ksh 中运行它,ksh 将被传递 for f in $(folders); do cd "$${f}" && pwd; pwd; cd ..; done,它将在那个子 shell 中运行。如果 ksh 没有实现 for 循环,这可能会出错,并且 make 会说命令返回了一些错误代码。


pwd_test 的解释

pwd_test:
    @cd "test0" && pwd
    @pwd

@cd "test0" && pwd被视为一行,因此 subshel​​l 更新其当前工作目录,然后打印出当前工作目录。

@pwd在这一行,make 生成了一个新的子shell,其中包含旧的工作目录(或者目录 make 被称为 form)并pwd打印该目录。

于 2013-05-02T13:51:29.517 回答