/ 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