![foo라는 디렉터리에서 모든 파일을 찾습니다.](https://linux55.com/image/160834/foo%EB%9D%BC%EB%8A%94%20%EB%94%94%EB%A0%89%ED%84%B0%EB%A6%AC%EC%97%90%EC%84%9C%20%EB%AA%A8%EB%93%A0%20%ED%8C%8C%EC%9D%BC%EC%9D%84%20%EC%B0%BE%EC%8A%B5%EB%8B%88%EB%8B%A4..png)
모든 디렉토리에 있는 모든 파일을 찾고 싶습니다 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
사용되지 않지만 find
셸 zsh
에서는 와일드카드로 사용됩니다.
$ 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
).
bash
glob 한정자가 없기 때문에 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 -prune
find를 사용하면 foo
해당 디렉터리에서 중지됩니다. ! -name foo
정리가 수행되지 않으므로 foo/foo
유사한 파일이 foo/foo/bar
두 번 보고됩니다. 외부적으로 해석되기 때문에 -exec
내부적으로 사용할 수 없습니다 . 가지고 있다면 (다음 버전의 POSIX에 포함하는 것을 고려하고 있다면) 이를 안정적으로 만들 수 있지만 여전히 다음과 같은 제한 사항이 있습니다 .find
{}
find
find
-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