/ src / 아래에 수많은 파일이 있다고 생각하십시오
cp /src/* /dst/
몇 개의 파일 cp이 성공적으로 처리됩니까?
답변
이는 시스템과 버전, 인수의 수와 크기, 환경 변수 이름의 수와 크기에 따라 크게 다릅니다.
전통적으로 Unix에서 (에 의해보고 된 getconf ARG_MAX) 한계 는 다음과 같은 누적 크기에 다소 차이가있었습니다.
- 인수 문자열의 길이 (종료 포함
'\0') - 해당 문자열에 대한 포인터 배열의 길이이므로 일반적으로 64 비트 시스템에서 인수 당 8 바이트
- 환경 문자열 (종료 포함)의 길이이며, 환경
'\0'문자열은 다음과 같은 규칙에 따릅니다var=value. - 해당 문자열에 대한 포인터 배열의 길이이므로 일반적으로 64 비트 시스템에서 인수 당 8 바이트
cp인수로 간주되는 것을 명심 하십시오 (첫 번째 인수입니다).
Linux에서는 버전에 따라 다릅니다. 최근 고정 된 공간이 아닌 곳에서 동작이 변경되었습니다.
Linux 3.11에서 검사 getconf ARG_MAX하면 스택 크기에 설정된 한계의 1/4 또는 512kiB보다 작은 경우 128kiB가보고됩니다.
( zsh아래 구문) :
$ limit stacksize
stacksize 8MB
$ getconf ARG_MAX
2097152
$ limit stacksize 4M
$ getconf ARG_MAX
1048576
그 한계는 인수 및 환경 문자열의 누적 크기와 약간의 오버 헤드 (페이지 경계에 대한 정렬 고려로 인해 의심됩니다)에 있습니다. 포인터의 크기는 고려되지 않습니다.
한도를 검색하면 다음과 같은 결과가 나타납니다.
$ /bin/true {1..164686}
$ /bin/true {1..164687}
zsh: argument list too long: /bin/true
$ x= /bin/true {1..164686}
$ x=1 /bin/true {1..164686}
zsh: argument list too long: /bin/true
이 경우 중단 전 최대 누적 크기는 다음과 같습니다.
$ (env _=/bin/true x=;print -l /bin/true {1..164686}) | wc -c
1044462
그렇다고 백만 개의 빈 인수를 전달할 수있는 것은 아닙니다. 64 비트 시스템에서 백만 개의 빈 인수는 8MB의 포인터 목록을 만들며 스택 크기는 4MiB보다 큽니다.
$ IFS=:; /bin/true ${=${(l.1000000..:.)${:-}}}
zsh: killed /bin/true ${=${(l.1000000..:.)${:-}}}
(E2BIG 오류가 아니라는 것을 알 수 있습니다. execve시스템 호출 내에 있거나 이후에 프로세스가 종료되는 시점은 확실하지 않습니다 ).
또한 스택의 크기에 관계없이 단일 인수 또는 환경 문자열의 최대 크기는 128kiB입니다 (Linux 3.11에서는 여전히).
$ /bin/true ${(l.131071..a.)${:-}} # 131072 OK
$ /bin/true ${(l.131072..a.)${:-}} # 131073 not
zsh: argument list too long: /bin/true
$ /bin/true ${(l.131071..a.)${:-}} ${(l.131071..a.)${:-}} # 2x 131072 OK
답변
이는 시스템간에 변경 될 수있는 ARG_MAX의 값에 따라 다릅니다. 시스템 실행 값을 찾으려면 (예를 들어 내 결과를 보여줍니다) :
$ getconf ARG_MAX
2097152
이것은 cp쉘이나 쉘 과 관련이 없으며 커널이 부과하는 한계이며 exec()인수가보다 긴 경우 ( ) 명령을 실행하지 않습니다 ARG_MAX. 따라서 제공 한 인수 목록의 길이 cp가 ARG_MAX보다 길면 cp명령이 전혀 실행되지 않습니다.
주요 질문에 대답하려면 cp너무 많은 인수로 실행되지 않으므로 파일을 처리하지 않습니다. 나는 이것이 인수의 수에 의존하지 않고 길이에 달려 있다고 언급해야합니다. 파일 이름이 적지 만 매우 긴 경우에도 동일한 문제가 발생할 수 있습니다.
이러한 오류를 해결하는 방법은 명령을 루프로 실행하는 것입니다.
for file in /src/*; do cp "$file" /dst/; done