如何在所有子目录中执行make

如何在所有子目录中执行make

我有几个目录,其中有 Makefile。

我制作了这个脚本来运行这些 Makefile(如果存在):

find . -name "Makefile" -exec sh -c 'make re -C "$1" $(dirname "$0")' {} \;

但它似乎不起作用,我收到此错误:

make: the `-C' option requires a non-empty string argument
Usage: make [options] [target] ...
Options:
  -b, -m                      Ignored for compatibility.
  -B, --always-make           Unconditionally make all targets.
  -C DIRECTORY, --directory=DIRECTORY
[...]

但是当我替换make re -Cechoor时printf它工作正常......

find . -name "Makefile" -exec sh -c 'printf "%s\n" "$1" $(dirname "$0")' {} \;
# or
find . -name "Makefile" -exec sh -c 'echo "$1" $(dirname "$0")' {} \;

答案1

您的原始代码使用两个参数$0$1,但您只在 中传递一些内容$0,留空$1。这会导致make你以你所表现的方式抱怨。

可以如果您愿意,可以通过简单地从您的命令中删除"$1"(并引用周围的命令替换)来解决此问题,假设您不介意操作数和选项的顺序混合,但我也会给您一些其他想法。dirnamemake


下面的两个命令查找Makefile当前目录中或当前目录下调用的所有常规文件,然后用于在找到此类文件的每个目录中make -C创建目标。re

find . -name Makefile -type f -exec sh -c 'make -C "${1%/*}" re' sh {} \;

或者

find . -name Makefile -type f -exec sh -c '
  for pathname do
      make -C "${pathname%/*}" re
  done' sh {} +

在第二个命令中,我更改了sh -c脚本以循环尽可能多的找到的路径名,而不仅仅是单个名称。

我已将dirname这两个命令替换为标准参数扩展,该扩展从$pathname.我们知道至少有即使Makefile在当前目录中找到该文件,路径名中也会包含斜杠,这使得此操作安全;否则这是一种边缘情况,您想要更换dirname更快的替代品。


一个不make与其选项一起使用的更快速的变体是使用来自的(非标准)谓词-C运行:make-execdirfind

find . -name Makefile -type f -execdir make re \;

这会导致find将工作目录更改为找到make该文件的目录。Makefile这个变体的好处是它make直接执行而不处理sh -c脚本。

答案2

与其使用它,不如直接进入目录make -C更容易。cd

这个实现工作正常:

find . -name "Makefile" -exec sh -c 'cd "$(dirname "$0")" && make re' {} \;

相关内容