"find -exec"를 사용하여 찾은 파일의 디렉터리(현재 디렉터리가 아님)에서 명령을 실행하는 방법은 무엇입니까?

"find -exec"를 사용하여 찾은 파일의 디렉터리(현재 디렉터리가 아님)에서 명령을 실행하는 방법은 무엇입니까?

내가 있는 디렉토리에 , 및 하위 디렉토리가 있다고 dir1가정 dir2합니다 dir3. 각 디렉토리에는 파일이 있으며 각 디렉토리의 각 디렉토리에서 동일한 명령을 실행하고 해당 디렉토리 내부에서 명령을 실행하고 foo싶습니다 .foo

내가 "손으로" 수행했다면 다음과 같을 것입니다.

cd dir1
(execute on foo)
cd ../dir2
(execute on foo)
cd ../dir3
(execute on foo)

이 명령을 실행해야 합니다.각 디렉토리에서. foo일괄 예약 스크립트(궁금한 경우 HTCondor용)이며 예약 스크립트에 의해 시작된 실행의 출력이 각 하위 디렉터리에서 끝나도록 각 하위 디렉터리에서 실행되어야 합니다.

질문"파일 디렉터리에서 파일 찾기 및 명령 실행내가 아는 한, 내 질문에 대한 답은 없습니다. 질문에 대한 첫 번째 대답은 해결 방법에 가깝고 내 경우에는 작동하지 않으며 두 번째 대답은 사용 방법을 알 수 있을 만큼 충분하지 않습니다.

답변1

find지원한다고 가정하면 -execdir대신 이 옵션을 사용하세요.-exec

find . -type f -name 'foo' -execdir pwd \;

그러면 각 디렉터리로 차례로 변경되고 foo해당 파일이 있으면 실행됩니다 pwd.

참고: 이 솔루션의 용도를 변경하여 이름이 지정된 디렉터리에서 명령을 실행할 수는 없습니다 foo. 이렇게 하려면 제공된 각 매개변수를 반복 하고 각 매개변수를 차례로 사용 -exec sh -c '...'하는 간단한 접근 방식 으로 돌아가야 합니다. 이 예제는 각 디렉터리에서 실행됩니다.shcdpwd

find . -type d -name 'foodir' -exec sh -c '
    for d in "$@"; do ( cd "$d" || exit; pwd ); done
    ' _ {} +

답변2

명령을 실행할 디렉터리를 정확히 알고 있다고 가정하면,

for dir in dir1 dir2 dir3; do
    ( cd "$dir" && somecommand foo )
done

또는 foo파일을 반복하여

for foo in ./*/foo; do
  ( cd "${foo%/foo}" && somecommand foo )
done

서브쉘은 cd작업 디렉토리가 스크립트의 나머지 부분에 영향을 미치는 것을 방지합니다. 인수 ${foo%/foo}대체는 파일이 있는 디렉터리의 이름까지 확장됩니다(값에서 Knows 접미사 문자열을 제거하여 foo)./foo$foo

동일한 작업을 수행하려면 표준을 사용하십시오( find파일이 디렉토리 구조에 깊이 있을 수 있는 경우).foo

find . -type f -name foo -exec sh -c '
    for foo do
        ( cd "${foo%/foo}" && somecommand foo )
    done' sh {} +

즉:현재 디렉토리나 그 아래 어디에서나 "foo"라는 이름의 모든 일반 파일을 찾아 해당 경로 이름을 이 쉘 스크립트에 대량으로 제공합니다. 쉘 스크립트는 주어진 경로명을 반복하고, 디렉토리를 각 경로명의 디렉토리 부분으로 변경하고, 성공하면 실행되어야 합니다 somecommand foo.

비표준을 사용하는 솔루션은 -execdir다음을 참조하세요.엠마 루오의 답변. 그의 대답은 내 예에 적합합니다.

find . -type f -name foo -execdir somecommand foo ';'

답변3

예쁘지는 않을지 모르지만 일을 끝내는 것 같아요

find . -name 'foo' -type f -exec sh -c 'cd $(echo {}|cut -d"/" -f2) && ./foo' \;

답변4

Win 10의 WSL 및 GitBash에서 테스트되었습니다.

이전 솔루션의 execdir은 현재 디렉터리로 들어가는 대신 현재 디렉터리를 인수로 사용하여 명령이 실행되기 때문에 작동하지 않습니다.
디렉토리에 CD를 넣고 원하는 작업을 수행하면 됩니다.
예를 들어 작업을 시작하기 전에 모든 리포지토리를 업데이트하는 데 사용하는 것입니다.

find $HOME/workspace/ -maxdepth 1 -type d -name "repo*" -exec bash -c "cd \"{}\" && echo ____Pulling from \"{}\" && git pull" \;

편집:
PC/노트북을 사용하지 않고 더 강력한 코드가 필요한 경우 외부 명령을 사용하여 삽입할 수 없는 스크립트를 작성해야 합니다. 예를 들면 다음과 같습니다.

#!/bin/sh
find "$HOME/workspace/" -maxdepth 1 -type d -exec sh -c '
  for dir in "$@"
  do
    echo "____Pulling from $dir"
    cd "$dir"
    git pull
  done' sh {} +

관련 정보