CP : 복사 유틸리티의 최대 소스 파일 수 인수 파일이 있다고

/ 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