"포함 폴더 내의 여러 하위 디렉터리에 있는 파일에 대해 명령을 실행"하는 방법(예: 파일이 포함된 각 하위 디렉터리로 CD를 이동하고 명령을 실행)

"포함 폴더 내의 여러 하위 디렉터리에 있는 파일에 대해 명령을 실행"하는 방법(예: 파일이 포함된 각 하위 디렉터리로 CD를 이동하고 명령을 실행)

다른 디렉토리에 filename.sh라는 파일이 있습니다. 여러 클러스터 노드에서 동시에 실행되도록 이 파일을 제출하려고 합니다. 이 파일이 어디에 있든 찾아서 해당 폴더에 CD를 넣고 "sbatch run_code.sh" 명령을 실행해야 합니다. 이것이 제가 시도한 것입니다.

find . -mindepth 1 -type f -name filename.sh -exec sbatch run_code.sh {} \;

코드를 실행하는 데 필요한 종속성이 포함되지 않은 현재 폴더에서 명령을 실행한다는 점을 제외하면 작동합니다.

아니면 나는 이런 for 루프를 선호한다

for d in dirname; do 
  cd "$(dirname "$(find . -type f -name filename.sh)")" && sbatch run_code.sh)
done 

이것은 작동하지 않습니다. 여기서 도움을 받을 수 있기를 기대합니다. 제발.

답변1

당신이 원하는 것 같아요 :

find . -name filename.sh -type f -execdir sbatch run_code.sh {} ';'

-mindepth 1중복됩니다. 제외되지만 .어쨌든 and에 의해 제외됩니다 ..-type f-name filename.sh

-execdir(BSD에서)은 표준 술어는 아니지만 지원 find하는 경우 지원될 수 있습니다 (GNU에서는 비표준이기도 하지만) .find-mindepth-execdir

-execdir바로 이것입니다. 이는 -exec선택한 파일의 상위 디렉터리에서 명령을 실행하는 것과 같습니다. 여기서 find구현에 따라 실행되는 명령은 sbatch run_code.sh ./filename.sh또는 입니다 sbatch run_code.sh filename.sh. 명령에 인수로 전달하지 {}않으려면 filename.sh제거하십시오 .

find지원되지 않는 구현 의 경우 -execdir다음을 수행할 수 있습니다.

find . -name filename.sh -type f -exec sh -c '
  cd "${1%/*}" && exec sbatch run_code.sh "${1##*/}"' sh {} ';'

${1%/*}그러나 $1가장 짧은 꼬리 일치 항목을 제거하므로 더 효율적이고 안정적으로 /*작동합니다 . 가장 긴 헤더 일치 항목을 제거하면 비슷한 결과가 나타납니다 ."$(dirname -- "$1")"${1##*/}*/basename

또는 sh파일당 하나씩 실행하지 마세요.

find . -name filename.sh -type f -exec sh -c '
  for file do
    (cd "${file%/*}" && exec sbatch run_code.sh "${file##*/}"
  done' sh {} +

셸을 사용하면 zsh다음 작업도 수행할 수 있습니다.

for f (./**/filename.sh(ND.)) (cd $f:h && sbatch run_code.sh $f:t)

( (저장 프로세스) 는 서브셸에서 실행되는 마지막 명령에 대해 이미 암시적으로 사용되었으므로 exec필요하지 않습니다 .)zsh

$f:h$fead h(디렉토리 이름) 및 해당 $f:tail t(기본 이름) 으로 확장됩니다 .


예를 들어, 디렉토리 이름이 개행 문자로 끝나는 경우에도 여전히 작동합니다. dirname(또는 zsh's $var:h)를 사용하면 더 나은 결과를 얻을 수 있지만, 를 가져오는 경로에 문자가 dirname포함되지 않거나 /문자로 끝나는 경우도 있습니다. ./

관련 정보