다른 찾기로 파이프 찾기가 작동하지 않습니다.

다른 찾기로 파이프 찾기가 작동하지 않습니다.

내 사용 사례는 다음과 같습니다.

전체 시스템에서 X라는 디렉터리를 검색하세요.

물론 다음 줄은 작동합니다.

find / -type d -name "X"

다만, 속도가 좀 느린 편이고, 리소스를 많이 사용하는 것 같아요.

속도를 높이기 위해 찾기 결과를 다른 디렉터리로 전송하여 가능한 검색 결과를 필터링하는 것을 고려했습니다. 예를 들어 루트 디렉터리에서 대문자로 시작하는 디렉터리만 찾으려면 그 안에서 다음과 같은 디렉터리를 찾습니다.엑스.

find / -maxdepth 1 -type d -name "/[A-Z]*" | xargs find -type d -name "X"

그러나 이것은 작동하지 않았습니다.

나는 이미 그것을 보았다find의 출력을 다른 find로 파이프하는 방법하지만 검색을 위한 파이프라인 지침을 찾을 수 없습니다.

조회를 다른 조회로 파이프하려면 어떻게 해야 합니까?

답변1

할 수 있는find이 구문을 사용하지 않고 다른 결과에 따라 실행됩니다 find.

find / -maxdepth 1 -type d -name "/[A-Z]*" | xargs find -type d -name "X"

xargs첫째, 출력되는 파일 이름에 공백 문자, 따옴표 또는 백슬래시(또는 일부 구현에서는 문자가 아닌 문자)가 포함되지 않는 한 명령이나 다른 명령의 출력에 유사한 방법을 사용할 수 없습니다 .findfind

xargs임의의 파일을 처리하려면 출력에서 ​​비표준 옵션 만 사용할 수 있습니다 (이 역시 비표준임) . 출력 자체는 전혀 사후 처리할 수 없습니다(참조:-0find -print0-print0find -print찾기 결과를 반복하는 것이 왜 나쁜 습관입니까?).

추가적으로, xargs여기서는추가의두 번째 명령에 대한 파일 경로를 선택 find하고 필터 조건을 형성하는 조건자 뒤에 배치합니다. find작업할 파일 목록을 제공해야 합니다.앞으로어떤 술어.

xargs보다 일반적 으로, / (및 일부 / ) 조건자를 사용하여 찾은 파일에 대해 명령을 실행하기 위한 자체 내장 지원(더 안정적이고 일반적으로 더 효율적인)이 있으므로 의 출력에 사용할 필요가 거의 없습니다 .findfind-exec-ok-execdir-okdir

그러나 와 마찬가지로 xargs두 번째 파일 목록이 조건자 앞에 오는지 확인해야 하므로 find다음과 같아야 합니다.

find / -maxdepth 1 -name '[[:upper:]]*' -type d -exec sh -c '
   exec find "$@" -name X -type d' sh {} +

-exec cmd {} +가능한 한 많은 경로를 전달하기 위해 like 형식을 사용 하지만 마지막에만 전달할 수 있습니다. 두 번째 올바른 위치로 이동하는 데 사용됩니다.-execxargscmdshfind

또한 -name전체 경로(필요한 경로 -path)가 아니라 파일 이름이 일치한다는 점에 유의하세요. 따라서 대문자로 시작하는 파일 이름을 일치시키기 위해 [[:upper:]]*필요하지 않습니다 /[[:upper:]]*( 대개 일치는 로케일에 따라 매우 무작위입니다).[A-Z]*

GNU의 다음 버전 find(또는 현재 개발 버전)을 사용하면 다음 작업도 수행할 수 있습니다.

find / -maxdepth 1 -name '[[:upper:]]*' -type d -print0 |
  find -files0-from - -name X -type d

여기에서는 단일 호출로 전체 프로세스를 완료할 수 있습니다 find.

find / -path '/[![:upper:]]*' -prune -o -name X -type d -print

X라는 디렉터리를 찾기 전에 find이름이 대문자 이외의 문자로 시작하는 디렉터리로 시작하는 트리의 가지를 잘라내라고 알려줍니다./

일부 시스템(GNU 시스템의 GNU 포함)의 일부 구현 에서는 find현재 로케일에 유효하지 않은 텍스트인 파일 이름 부분을 일치시키는 것이 불가능할 수 있습니다.find*

예를 들어 위 명령은 대문자가 아니더라도 /stéphane/Xiso8859-1 로 인코딩되고 현재 로케일이 문자 맵으로 UTF-8을 사용하는 경우(0xe9 바이트를 문자로 디코딩할 수 없고 따라서 일치하지 않을 수 있습니다.) 그리고 첫 번째 명령도 같은 이유로 발견되지 않습니다.sé*/Stéphane/X

zshglob에는 문자로 디코딩할 수 없는 모든 바이트가 정의되지 않은 문자로 처리되므로 이러한 문제가 없습니다. 따라서 다음과 같이 할 수 있습니다.

print -rC1 /[[:upper:]]*/**/X(ND/)

또는 목록을 정렬할 필요가 없으면 o약간의 최적화를 수행할 수 있습니다.

print -rC1 /[[:upper:]]*/**/X(ND/oN)

여기에는 /SymLink/.../X디렉터리가 포함됩니다. 이를 방지하려면:

(){print -rC1 $^@/**/X(ND/oN)} /[[:upper:]]*(N/oN)

또는:

print -rC1 /[[:upper:]]*(N/oNe['reply=($REPLY/**/X(ND/oN)'])

이는 2단계 find접근 방식과 유사합니다. 이름이 glob에서 대문자로 시작하는 디렉터리를 찾은 다음 그 안의 모든 X 디렉터리를 별도의 glob으로 처리합니다.

답변2

당신의 임무는 첫 글자가 대문자인 하위 디렉토리를 찾은 /다음 이 하위 디렉토리의 경로 이름을 추출하는 것입니다 X.

의 경우 첫 글자를 대문자로 쓴 디렉토리가 find수천 개가 아니라고 가정하면 이렇게 할 것입니다 ./

find /[[:upper:]]*/X -prune -type d -print 

위에서 우리는 find일련의 최상위 검색 경로를 사용하여 호출했습니다. 이 경로 이름은 실제로 찾고 있는 디렉터리 이름과 정확히 일치합니다. 유일한 작업 find은 각각을 조사하고 목차를 인쇄하는 것입니다.

find완전히 건너뛰고 그냥 사용할 수도 있습니다.

printf '%s\n' /[[:upper:]]*/X/

여기서 유일한 차이점은 패턴이 디렉토리에 대한 기호 링크와 일치할 수 있다는 것입니다. 이것이 중요하다면 일치하는 이름에 대해 보다 명시적인 테스트를 수행하고 bash숨겨진 이름도 일치하도록 쉘에 지시할 수 있습니다.

shopt -s nullglob

for name in /[[:upper:]]*/X/; do
    [ -L "$name" ] && continue
    printf '%s\n' "$name"
done

귀하의 질문을 몇 번 다시 읽은 후에 나는 귀하가 검색을 원하는지 몰랐다는 것을 깨달았습니다.X 재귀적아니면. 위의 토론에서 나는 당신이 그렇게 가정합니다아니요재귀적으로 검색하고 싶습니다.

만약 너라면하다재귀적으로 검색하려면 다음을 사용합니다.

find /[[:upper:]]* -name X -type d -print

검색을 더 적은 수의 최상위 검색 경로로 제한하거나 사용하는 알려진 경로를 정리하지 않는 한 이 작업을 더 빠르게 할 수 있는 방법은 없습니다.알다검색을 원하지 않습니다. 예를 들어 tmp디렉토리를 입력하지 마십시오.

find /[[:upper:]]* -name X -type d -print -o -name tmp -prune

검색을 단일 파일 시스템으로 제한할 수 있습니다.

find /[[:upper:]]* -xdev -name X -type d -print -o -name tmp -prune

여기서 최상위 검색 경로의 검색은 파일 시스템 경계를 넘지 않습니다.

관련 정보