나는 많은(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 globstar
set -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
사용하지 않습니다.)