디렉터리의 파일을 재귀적으로 탐색

디렉터리의 파일을 재귀적으로 탐색

다음을 통해 디렉터리의 파일을 재귀적으로 쉽게 반복할 수 있습니다.

find . -type f -exec bar {} \;

그러나 위의 방법은 수행해야 할 조건부 분기, 루프 등이 많기 때문에 더 복잡한 작업에는 적합하지 않습니다. 나는 이것을 위에서 사용했습니다 :

while read line; do [...]; done < <(find . -type f)

그러나 이는 모호한 문자가 포함된 파일에서는 작동하지 않는 것 같습니다.

$ touch $'a\nb'
$ find . -type f
./a?b

이러한 모호한 문자를 잘 처리할 수 있는 다른 방법이 있습니까?

답변1

또 다른 용도가 있어요안전한find:

while IFS= read -r -d '' -u 9
do
    [Do something with "$REPLY"]
done 9< <( find . -type f -exec printf '%s\0' {} + )

(이것은 모든 POSIX에서 작동 find하지만 쉘 부분에는 bash가 필요합니다. *BSD 및 GNU find를 사용하면 -print0대신 find를 사용할 수 있으며 -exec printf '%s\0' {} +이는 약간 더 빠릅니다.)

이를 통해 루프 내에서 표준 입력을 사용할 수 있으며 다음과 함께 사용할 수 있습니다.어느길.

답변2

이를 수행하는 방법은 간단합니다.

find -exec sh -c 'inline script "$0"' {} \;

또는...

find -exec executable_script {} \;

답변3

가장 간단하지만 안전한 방법은 쉘 와일드카드를 사용하는 것입니다.

$ for f in *; do printf ":%s:\n" "$f"; done 
:a b:
:c
d:
:-e:
:e  f:
h:

위의 내용을 하위 디렉터리(bash에서)로 만들려면 이 옵션을 사용하여 이름이 다음으로 시작하는 파일과 일치하도록 globstar설정할 수도 있습니다 .dotglob.

$ shopt -s globstar dotglob
$ for f in **/*; do printf ":%s:\n" "$f"; done 
:a b:
:c
d:
:-e:
:e  f:
:foo:
:foo/file1:
:foo/file two:
h:

bash 4.2까지는 **/심볼릭 링크가 디렉터리로 반복된다는 점에 유의하세요. bash 4.3부터는 **/디렉토리로만 재귀됩니다 find.

또 다른 일반적인 솔루션은 다음 find -print0과 함께 사용하는 것입니다 xargs -0.

$ touch -- 'a b' $'c\nd' $'e\tf' $'g\rh' '-e'
$ find . -type f -print0 | xargs -0 -I{} printf ":%s:\n" {}
h:/g
:./e    f:
:./a b:
:./-e:
:./c
d:

h:/g파일 이름 에 \r.

답변4

휴대용으로 읽기 루프를 수행하는 것은 약간 어렵지만 특히 bash의 경우 다음과 같은 것을 시도해 볼 수 있습니다.이것.

관련 부품:

while IFS= read -d $'\0' -r file ; do
        printf 'File found: %s\n' "$file"
done < <(find . -iname 'foo*' -print0)

findNUL 문자(0x00)로 구분된 출력을 인쇄하고 백슬래시를 다른 문자에 대한 이스케이프( )로 처리하지 않고 행( )의 토큰화를 수행하지 않고 readNUL로 구분된 행( )을 가져오도록 지시합니다 . 0x00은 Unix의 파일 이름이나 경로에 나타날 수 없는 바이트이므로 모든 이상한 파일 이름 문제를 처리해야 합니다.-d $'\0'-rIFS=

관련 정보