foo라는 디렉터리에서 모든 파일을 찾습니다.

foo라는 디렉터리에서 모든 파일을 찾습니다.

모든 디렉토리에 있는 모든 파일을 찾고 싶습니다 foo. 예를 들어 다음 파일을 고려해보세요.

foo/w
a/foo/x
a/b/foo/y
a/b/c/foo/z
a/b/c/foo/bar/n

w,x,y,z이 파일을 찾아서 위와 같이 상대 경로와 함께 나열하고 싶습니다 . 나의 시도는 이렇다

$ find . -path '**/foo' -type f

이것은 작동하지 않습니다. 검색에는 file 이 포함되어서는 안 됩니다 n. 즉, foo상위 디렉터리 이름이 관심 있는 파일만 포함해야 합니다.

답변1

사용되지 않지만 findzsh에서는 와일드카드로 사용됩니다.

$ printf '%s\n' **/foo/*(^/)
a/b/c/foo/z
a/b/foo/y
a/foo/x
foo/w

이는 **"재귀적으로" 디렉터리를 일치시키고 foo현재 디렉터리 또는 아래 디렉터리에 지정된 모든 디렉터리를 일치시킨 다음 해당 디렉터리의 모든 파일을 *(^/)일치시키는 glob을 사용합니다. 패턴을 일치하는 디렉터리( 일반 파일만 일치시키거나 일반 파일에 대한 기호 링크도 포함) 로 제한하는 glob 한정자로 끝 foo납니다 .(^/)(.)(-.)

존재하다 bash:

shopt -s globstar nullglob

for pathname in **/foo/*; do
    if [[ ! -d "$pathname" ]] || [[ -h "$pathname" ]]; then
        printf '%s\n' "$pathname"
    fi
done

패턴이 일치하지 않을 경우 패턴을 완전히 제거하는 nullglob옵션을 설정했습니다.bash아무것. 쉘 globstar옵션을 사용하면 **in을 사용할 수 있습니다 bash(기본적으로 활성화됨 zsh).

bashglob 한정자가 없기 때문에 zsh패턴과 일치하는 경로 이름을 반복하고 각 일치 항목을 테스트하여 인쇄하기 전에 디렉터리가 아닌지 확인합니다. " ! -d || -h" 테스트를 " -f && ! -h" 테스트로 변경하여 일반 파일만 선택하거나 단일 " -f" 테스트만 선택하여 일반 파일에 대한 기호 링크를 인쇄합니다.

답변2

**find패턴에는 특별한 의미가 없습니다. 하위 디렉토리의 파일을 포함하여 -path '*/foo/*'이름이 지정된 디렉토리 아래의 모든 파일을 찾습니다 foo. 단 한 번의 POSIX 호출로는 이 -path '*/foo/*' ! -path '*/foo/*/*'작업 a/foo/b/foo/c을 수행할 수 없다고 생각합니다 find.

지원되는 구현(GNU, BusyBox, FreeBSD, NetBSD)을 사용하면 find이를 사용하여 -regex./foo

find . -regex '.*/foo/[^/]*' -type f

또는 를 사용하여 디렉토리와 쉘을 find찾아 해당 디렉토리의 파일을 열거할 수 있습니다 .foo

또 다른 가능한 접근 방식은 다시 호출하는 것이지만 실제로 작동하는 순수한 POSIX 솔루션을 find찾을 수 없습니다 . POSIX의 경우 find각 디렉토리에 대해 find다시 호출하십시오 .foo

find . -name foo -type d -exec find {} -type d ! -name foo -prune -o -type f \;

이것은 대부분 작동하지만 완전히 작동하지는 않으며 약간 취약합니다. 하위 디렉터리로 반복되는 것을 방지 해야 -type d -prune하지만 -type d -prunefind를 사용하면 foo해당 디렉터리에서 중지됩니다. ! -name foo정리가 수행되지 않으므로 foo/foo유사한 파일이 foo/foo/bar두 번 보고됩니다. 외부적으로 해석되기 때문에 -exec내부적으로 사용할 수 없습니다 . 가지고 있다면 (다음 버전의 POSIX에 포함하는 것을 고려하고 있다면) 이를 안정적으로 만들 수 있지만 여전히 다음과 같은 제한 사항이 있습니다 .find{}findfind-maxdepth-exec

find . -name foo -type d -exec find {} -maxdepth 1 -type f \;

POSIX 찾기 및 sh의 경우:

find . -name foo -type d -exec sh -c '
    for x in "$0/"* "$0/".*; do
      if [ -f "$x" ] && ! [ -L "$x" ]; then
        …;
      fi;
    done
' {} \;

파일 이름에 대해 실행하려는 코드를 .

답변3

RHEL7을 사용하고 있습니다. 이것은 나에게 효과적입니다.

find . -path "*/foo/*" ! -path '*/foo/*/*' -type f

-path 앞에 점을 적어 두십시오. (또는 /home/$USER와 같이 경로를 바꾸십시오)

이것가리키다"현재 디렉터리에서 검색 시작"이라고 말합니다.

이것- 작은 길"foo" 아래에 중첩된 디렉토리를 제외하고 "foo라는 이름의 하위 디렉토리가 뒤따르는 모든 것을 찾고, 그 뒤에 무엇이든 찾아라"를 의미합니다.

이것-f 유형나한테만 준다고 해문서일치하는 디렉토리에 있습니다.

좋다

-path "*/foo/*" ! -path '*/foo/*/*'  

그런 것들을 놓치기 때문에 모든 것을 얻을 수는 없습니다 ./a/foo/b/foo/c.

파일 및 디렉터리 이름에 개행 문자가 포함되지 않는다고 보장할 수 있는 경우 다음 명령을 사용하여 출력을 사후 처리할 수 있습니다 awk.

find . -path "*/foo/*" -type f | awk -F/ '$(NF-1) == "foo"'

답변4

가장 먼저 떠오르는 것은 다음과 같습니다.

find $ROOT_PATH -type d -name foo | xargs -n1 -I{} find {} -type f

관련 정보