find가 호출한 명령을 실행합니다.

find가 호출한 명령을 실행합니다.

find를 재귀적으로 호출하는 방법이 있나요?

다른 패턴과 일치하는 디렉터리에서만 특정 패턴과 일치하는 파일을 검색하고 싶습니다.

원래:

for each (sub)directory D matching "*.data"
do
  for each file F in directory D (with subdirs) matching "*.important.txt"
  do
    run command foo on F
  done
done

이제 가장 안쪽 요구 사항(F에서 foo 명령 실행) 이것은 매우 간단합니다.

find . -type d -name "*.data" \
     -exec find \{\} -type f -name "*.important.txt" \;

그러나 내부에서 명령을 전달하는 방법을 찾지 못했습니다 find. 예를 들어 다음을 인쇄해 보세요.찾기: '-exec' 인수 누락내부 조회가 호출될 때마다:

 find . -type d -name "*.data" \
      -exec find \{\} -type f -name "*.important.txt" \
                 -exec "foo \{\} \;" \;

모든 솔루션은 posix 규격(스크립트에서 실행 가능)이어야 합니다 /bin/sh. 나는 해결책을 찾고 있는 것이 아니다

  • 내부 조회를 별도의 쉘 스크립트로 래핑
  • 내부 조회를 bash 기능으로 래핑

답변1

find결과를 자체적으로 실행하려면 (or) -c인수를 사용하여 외부 find 명령이 내부 결과를 특별하게 처리하지 못하도록 할 수 있습니다. 그러나 외부 조회 결과를 다음을 사용하여 확장할 수 있는 매개변수로 전달해야 합니다.shbash{}sh$0

find . -type d -name "*.data" \
      -exec sh -c 'find "$0" -type f -name "*.important.txt" -exec echo \{\} \;' \{\} \;

참고: 공백이 포함된 디렉터리 이름 문제를 방지하려면 $0따옴표( "$0")를 사용해야 합니다.

find -exec이는 털이 많은 탈출 없이 임의로 깊은 중첩을 허용하지 않기 때문에 실제로 "재귀적" 솔루션은 아니지만 예제에서 요청한 두 가지 수준을 지원합니다 .

귀하의 예가 실제 문제와 유사하다면 매개변수를 사용하여 다음 -path을 찾아볼 수도 있습니다.

find . -path '*.data/*important.txt'

답변2

bash 버전(POSIX와 호환되지 않음)

#!/bin/bash
find . -type d -name 'a *' -print0 \
    | while IFS= read -r -d '' dir ; do
        find "$dir" -type f -name "*.c" -exec echo \{\} \;
    done

질문:


(나쁜) sh 버전(POSIX 호환)

#!/bin/sh
# WARNING: while this will work on directory names with spaces,
#          it will break on directory names that contain newlines
find . -type d -name 'a *' -print \
    | while IFS= read -r dir ; do
        find "$dir" -type f -name "*.c" -exec echo \{\} \;
    done

문제: 주석에서 언급했듯이 개행 문자가 포함된 디렉토리 이름에서 중단됩니다. 이것이 실제 문제라고 생각하지 않을 수도 있지만 스크립트에 불필요한 취약점을 추가합니다. 어쩌면 다른 프로그램에 그러한 디렉토리 등을 생성하는 버그가 있을 수 있습니다.


(더 나은) sh 버전

바라보다이안 로버트슨의 답변


그런데. POSIX와 호환되는 스크립트가 필요한 경우 다음을 사용하십시오.shellcheck. 예를 들어 read -dPOSIX에는 정의가 없다는 점을 알 수 있습니다 .

관련 정보