내 사용 사례는 다음과 같습니다.
전체 시스템에서 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
첫째, 출력되는 파일 이름에 공백 문자, 따옴표 또는 백슬래시(또는 일부 구현에서는 문자가 아닌 문자)가 포함되지 않는 한 명령이나 다른 명령의 출력에 유사한 방법을 사용할 수 없습니다 .find
find
xargs
임의의 파일을 처리하려면 출력에서 비표준 옵션 만 사용할 수 있습니다 (이 역시 비표준임) . 출력 자체는 전혀 사후 처리할 수 없습니다(참조:-0
find -print0
-print0
find -print
찾기 결과를 반복하는 것이 왜 나쁜 습관입니까?).
추가적으로, xargs
여기서는추가의두 번째 명령에 대한 파일 경로를 선택 find
하고 필터 조건을 형성하는 조건자 뒤에 배치합니다. find
작업할 파일 목록을 제공해야 합니다.앞으로어떤 술어.
xargs
보다 일반적 으로, / (및 일부 / ) 조건자를 사용하여 찾은 파일에 대해 명령을 실행하기 위한 자체 내장 지원(더 안정적이고 일반적으로 더 효율적인)이 있으므로 의 출력에 사용할 필요가 거의 없습니다 .find
find
-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 형식을 사용 하지만 마지막에만 전달할 수 있습니다. 두 번째 올바른 위치로 이동하는 데 사용됩니다.-exec
xargs
cmd
sh
find
또한 -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/X
iso8859-1 로 인코딩되고 현재 로케일이 문자 맵으로 UTF-8을 사용하는 경우(0xe9 바이트를 문자로 디코딩할 수 없고 따라서 일치하지 않을 수 있습니다.) 그리고 첫 번째 명령도 같은 이유로 발견되지 않습니다.s
é
*
/Stéphane/X
zsh
glob에는 문자로 디코딩할 수 없는 모든 바이트가 정의되지 않은 문자로 처리되므로 이러한 문제가 없습니다. 따라서 다음과 같이 할 수 있습니다.
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
여기서 최상위 검색 경로의 검색은 파일 시스템 경계를 넘지 않습니다.