파일이 발견되면 검색 트리 정리

파일이 발견되면 검색 트리 정리

이름이 특정 파일 이름 와일드카드 패턴과 일치하는 일반 파일을 찾기 위해 상당히 큰 디렉터리 계층 구조를 검색해야 합니다. 계층 구조가 너무 커서(매우 깊고 거대한 디렉터리가 있음) 간단한 접근 방식을 사용하면 시간이 너무 오래 걸립니다.

find /top/dir -type f -name 'pattern'

( pattern유사한 패턴은 어디에 있습니까 *proj*.tgz?)

디렉터리 구조의 특성으로 인해 find디렉터리에서 파일이 발견되면 검색 트리를 정리하기 위해 최적화를 도입할 수 있다는 것을 알고 있습니다. 예를 들어, 특정 디렉터리에서 하나 이상의 파일을 찾는다는 것은 해당 특정 디렉터리의 하위 디렉터리에서 다른 일치 항목을 확인할 필요가 없음을 의미합니다.

일반 파일 에 적용하는 것이 맞지 않아서 -prune이렇게 할 수 없습니다.

find /top/dir -type f -name 'pattern' -prune

질문: 패턴과 일치하는 파일이 포함된 디렉터리의 하위 디렉터리 검색을 방지하려면 어떻게 해야 합니까?

답변1

각 디렉토리에 대해 인라인 스크립트를 호출할 수 있습니다. 스크립트는 패턴이 디렉터리의 일반 파일과 일치하는지 확인합니다. 패턴이 일치하면 출력(일반적으로프로세스단순히 인쇄하는 대신) 경로 이름을 일치시키고 검색 트리에서 상위 디렉토리를 정리합니다.

find /top/dir -type d -exec zsh -c '
    set -- "$1"/pattern(.N)
    [[ $# -eq 0 ]] && exit 1
    printf "%s\n" "$@"' zsh {} \; -prune

인라인 스크립트의 셸을 사용하여 zsh셸의 전역 한정자에 액세스합니다. 여기에 사용된 한정자는 (.N)일반 파일만 패턴과 일치하는지 확인하고, 일치하는 파일이 없으면 패턴이 제거됩니다.


bash인라인 스크립트 의 경우 :

find /top/dir -type d -exec bash -O nullglob -c '
    unset -v found
    for pathname in "$1"/pattern; do
        if [[ -f "$pathname" ]] && [[ ! -h "$pathname" ]]; then
            printf "%s\n" "$pathname"
            found=true
        fi
    done
    "${found-false}"' bash {} \; -prune

즉, 특정 디렉터리의 패턴과 일치하는 이름을 통해 인라인 스크립트 루프를 갖고, 이름이 일반 파일에 해당하면 이를 처리하고 "플래그"를 설정합니다. 이 플래그가 끝에 설정되면 상위 디렉토리가 정리됩니다.

답변2

디렉터리 계층 구조를 탐색하여 플래그 파일이 발견되면 각 디렉터리의 트리를 정리하고( ), pattern그렇지 않으면 필요한 파일을 검색합니다( *proj*.tgz).

find /top/dir -type d -exec sh -c 'z=$(find "$@" -maxdepth 1 -type f -name "pattern" -print -quit); [ -n "$z" ]' _ {} \; -prune -o -type f -name '*proj*.tgz' -print

나는 무슨 일이 일어나고 있는지 볼 수 있는 더 복잡한 버전을 작성하게 되었습니다. 분명히 지역 관련 항목을 얻으려면 /top/dir, pattern및 를 변경해야 합니다 . *proj*.tgz) 나중에 이를 위해 여기에 포함하겠습니다.

find /top/dir -type d \
    -exec bash -c '
        echo "Considering $*";
        z=$(find "$@" -maxdepth 1 -type f -printf "| %p\n" -name "pattern" -printf "Found flag file\n" -quit);
        [[ -n "$z" ]] && echo "$z";
        [[ "$z" =~ "Found flag file" ]] || { echo "No flag found"; exit 1; }
    ' _ {} \; \
    -printf "Pruning tree\n" -prune \
    -o \
    -type f -name '*proj*.tgz' -print

실제 솔루션에는 POSIX가 아닌 것이 필요합니다 find -maxdepth. 디버그 빌드에는 POSIX가 아닌 빌드도 필요합니다 find -printf. 하나 있다대체 방법POSIX 준수를 구현하는 데 사용되지만 -maxdepth여기서는 코드 자체가 충분히 불투명합니다.

관련 정보