백틱 (또는 $ (...)) 확장에서 공백을 보호 할 방법이 없습니까?
아닙니다. 왜 그런 겁니까?
Bash는 무엇을 보호해야하고 무엇을 보호해야하는지 알 방법이 없습니다.
유닉스 파일 / 파이프에는 배열이 없습니다. 바이트 스트림 일뿐입니다. ``
또는 내부의 명령 $()
은 스트림을 출력합니다. 스트림은 bash가 삼키고 단일 문자열로 취급합니다. 이 시점에서 따옴표로 묶거나 하나의 문자열로 유지하거나 알몸으로 두어 선택하면 bash가 구성된 동작에 따라 분할됩니다.
따라서 배열을 원한다면 배열이있는 바이트 형식을 정의하고 도구가 좋아 xargs
하고 find
수행하는 것입니다. -0
인수를 사용하여 실행하면 요소를 종료하는 이진 배열 형식에 따라 작동합니다 그렇지 않으면 불투명 바이트 스트림에 의미를 추가하는 null 바이트
불행하게도, bash
널 바이트에서 문자열을 분할하도록 구성 할 수 없습니다. 이를 보여 주신 /unix//a/110108/17980 에게 감사드립니다 zsh
.
xargs
명령을 한 번만 실행하면 xargs -0 -n 10000
문제 가 해결 되었다고합니다 . 그러나 10000 개가 넘는 매개 변수가있는 경우 명령이 두 번 이상 실행됩니다.
엄격하게 한 번 실행하거나 실패하게하려면 -x
인수와 -n
인수보다 큰 인수 를 제공해야합니다 -s
(실제로 : 길이가 0 인 인수와 명령 이름이 일치하지 않을 정도로 커야 함) -s
크기). ( man xargs , 아래 발췌 부분 참조)
현재 사용중인 시스템의 스택은 약 8M로 제한되어 있으므로 내 한계는 다음과 같습니다.
$ printf '%s\0' -- {1..1302582} | xargs -x0n 2076858 -s 2076858 /bin/true
xargs: argument list too long
$ printf '%s\0' -- {1..1302581} | xargs -x0n 2076858 -s 2076858 /bin/true
(no output)
세게 때리다
외부 명령을 사용하지 않으려면 /unix//a/110108/17980에 표시된 것처럼 배열을 공급하는 while-read 루프 는 bash가 항목을 분할하는 유일한 방법입니다 null 바이트
( . ... "$@" )
스택 크기 제한을 피하기 위해 스크립트를 소싱하는 아이디어 는 훌륭하지만 (시도했습니다!) 정상적인 상황에서는 중요하지 않습니다.
stdin에서 다른 것을 읽으려면 프로세스 파이프에 특수 fd를 사용하는 것이 중요하지만 그렇지 않으면 필요하지 않습니다.
따라서 일상적인 가정 요구에 가장 간단한 "기본"방법 :
files=()
while IFS= read -rd '' file; do
files+=("$file")
done <(find ... -print0)
myscriptornonscript "${files[@]}"
프로세스 트리가 깨끗하고보기 좋으면이 메소드를 사용하면 exec mynonscript "${files[@]}"
bash 프로세스를 메모리에서 제거하고 호출 된 명령으로 대체 할 수 있습니다. xargs
명령이 한 번만 실행 되더라도 호출 된 명령이 실행되는 동안 항상 메모리에 남아 있습니다.
네이티브 bash 메소드에 반대하는 것은 다음과 같습니다.
$ time { printf '%s\0' -- {1..1302581} | xargs -x0n 2076858 -s 2076858 /bin/true; }
real 0m2.014s
user 0m2.008s
sys 0m0.172s
$ time {
args=()
while IFS= read -rd '' arg; do
args+=( "$arg" )
done < <(printf '%s\0' -- $(echo {1..1302581}))
/bin/true "${args[@]}"
}
bash: /bin/true: Argument list too long
real 107m51.876s
user 107m38.532s
sys 0m7.940s
bash는 배열 처리에 최적화되어 있지 않습니다.
남자 xargs :
-n 최대 값
명령 행당 최대 max-args 인수를 사용하십시오. -x 옵션을 지정하지 않은 경우 크기를 초과하면 (-s 옵션 참조) max-args보다 적은 인수가 사용됩니다.이 경우 xargs가 종료됩니다.
-s 최대 문자
명령 및 초기 인수 및 인수 문자열의 끝에있는 종료 널을 포함하여 명령 행당 최대 최대 문자 수를 사용하십시오. 허용되는 최대 값은 시스템에 따라 다르며 exec의 인수 길이 제한으로, 환경의 크기가 적고, 2048 바이트의 헤드 룸이 아닙니다. 이 값이 128KiB보다 크면 128Kib가 기본값으로 사용됩니다. 그렇지 않으면 기본값은 최대입니다. 1KiB는 1024 바이트입니다.
-엑스
크기가 초과되면 종료하십시오 (-s 옵션 참조).
IFS="
개행,"
)입니다. 그러나 모든 파일 이름에 대해 스크립트를 실행해야 합니까? 그렇지 않으면 find 자체를 사용하여 각 파일에 대한 스크립트를 실행하십시오.