すべてのサブディレクトリで 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
[...]

しかし、ormake re -Cと交換するとうまくいきます...echoprintf

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

答え1

元のコードは2つのパラメータとを$0使用します$1が、何かを渡すだけで空白のままにし$0ます$1。これはmake行動方法について不平を言うかもしれません。

あなたできる必要に応じて、"$1"オペランドとオプションの順序が混在していても構いません。コマンドから単に削除してコマンドの置き換えを引用してこの問題を解決できますが、いくつかの異なるアイデアを提供します。よく。dirnamemake


次の2つのコマンドは、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 {} +

2番目のコマンドでは、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' {} \;

関連情報