찾기 위한 루프용 Bash 스크립트 및 많은 디렉토리

찾기 위한 루프용 Bash 스크립트 및 많은 디렉토리

나는 많은(100,000+) 하위 디렉터리가 포함된 디렉터리에서 일부 작업을 수행하기 위해 bash 스크립트를 작성 중입니다. 아래와 같이 for 루프에 전달할 수 있는 매개변수 수에 미리 정의된 제한이 있습니까?

for dir in $(find . -type d)
do
  # My code
done

find 명령이 너무 많은 디렉터리를 반환하면 스크립트가 실패할까봐 걱정됩니다.

답변1

find 출력을 구문 분석하지 말고 쉘 와일드카드만 사용하십시오. 이는 더 안전하고 쉘에 내장되어 있습니다. 쉘 내장(예: for외부 프로세스)에는 호출이 이루어지지 않기 때문에 외부 프로세스와 동일한 매개변수 목록 길이 제한이 적용되지 않습니다 exec*.

for dir in ./*/; do
    # ...
done

답변2

가 있는 경우 bash 4다음과 같은 재귀적인 작업을 수행할 수 있습니다.

shopt -s globstar
for dir in **/; do echo "$dir"; done

답변3

귀하가 수락한 답변에 동의하지 않습니다.~ 할 것이다$(find)사용하시면 선물이 없어도 메모리 문제가 발생합니다 exec.

대신 다음과 같이 작성하세요.

find . -type d | while IFS= read -r dir
do
  # My code
done

(참고: 이는 개행 문자가 포함된 디렉터리 이름이 없다고 가정합니다.)

find그러면 명령 대체처럼 출력을 저장하기 위해 임시 메모리를 사용할 필요가 없습니다 . 이 명령 find이나 다른 명령이 종료되지 않는 경우에도 작동합니다. 예를 들면 다음과 같습니다.

# will not work!
for line in $(yes) ; do echo "$line" ; done

# works
yes | while IFS= read -r line ; do echo "$line" ; done

답변4

파일 이름을 생성하기 위해 명령 대체를 사용하지 마십시오. 파일 이름에 공백이 포함되어 있거나 \[?*.

bash ≥4, ksh93 또는 zsh의 경우 glob을 사용하여 모든 깊이의 하위 디렉터리와 일치시키면 대부분 find-type d또는 술어 사용을 피할 수 있습니다. Bash에서는 먼저 실행하십시오. ksh에서 먼저 실행하십시오.-name …**shopt -s globstarset -o globstar

for dir in **/; do …; done

휴대용이거나 더 필요한 경우 find … -exec … +또는 를 사용하세요 find … -print0 | xargs -0 …. 이 접근 방식의 또 다른 이점은 find파일에 대한 작업과 어느 정도 병렬로 실행된다는 것입니다. 하지만 이는 거대한 디렉터리 트리(적어도 수천 개의 일치하는 파일)에서만 작동합니다. 명령 실행 이상의 작업이 필요한 경우 find셸을 만들거나 실행할 수 있습니다.xargs

find -type d -exec sh -c 'for x in "$@"; do echo "$x"; done' _ {} +

(이것은 쉘 조각에 _있으므로 $0사용하지 않습니다.)

관련 정보