모든 하위 디렉터리에서 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
[...]

하지만 or make 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

원래 코드는 두 개의 매개변수 $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' {} \;

관련 정보