Odpowiedzi:
Zależy to w dużej mierze od systemu i wersji, liczby i wielkości argumentów oraz liczby i wielkości nazw zmiennych środowiskowych.
Tradycyjnie w Uniksie limit (jak donosi getconf ARG_MAX
) był mniej więcej w stosunku do łącznego rozmiaru:
'\0'
)'\0'
), przy czym ciąg znaków środowiska jest umownie podobny var=value
.Pamiętając, że cp
również liczy się jako argument (jest to pierwszy argument).
W systemie Linux zależy to od wersji. Zachowanie tam się ostatnio zmieniło, gdy nie jest to już stała przestrzeń.
Sprawdzanie w systemie Linux 3.11 getconf ARG_MAX
pokazuje teraz jedną czwartą limitu ustawionego na stosie lub 128 kB, jeśli jest to mniej niż 512 kB.
( zsh
składnia poniżej):
$ limit stacksize
stacksize 8MB
$ getconf ARG_MAX
2097152
$ limit stacksize 4M
$ getconf ARG_MAX
1048576
Limit ten dotyczy skumulowanego rozmiaru argumentów i ciągów środowiska oraz pewnych kosztów ogólnych (podejrzewam, że ze względu na wyrównanie na granicach strony). Rozmiar wskaźników nie jest brany pod uwagę.
Szukając limitu, otrzymuję:
$ /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
Maksymalny łączny rozmiar przed zerwaniem w tym przypadku wynosi:
$ (env _=/bin/true x=;print -l /bin/true {1..164686}) | wc -c
1044462
To nie znaczy, że możesz przekazać milion pustych argumentów. W systemie 64-bitowym 1 milion pustych argumentów tworzy listę wskaźników o wielkości 8 MB, która byłaby powyżej mojego rozmiaru stosu wynoszącego 4 MB.
$ IFS=:; /bin/true ${=${(l.1000000..:.)${:-}}}
zsh: killed /bin/true ${=${(l.1000000..:.)${:-}}}
(zauważysz, że nie jest to błąd E2BIG. Nie jestem pewien, w którym momencie proces zostaje tam zabity, jeśli jest w ramach execve
wywołania systemowego lub później).
Zwróć także uwagę (nadal w Linuksie 3.11), że maksymalny rozmiar pojedynczego argumentu lub łańcucha środowiska wynosi 128kiB, niezależnie od wielkości stosu.
$ /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
164686
numer? tj. jak obliczyłeś, że sekwencja będzie 2097152
mniejsza niż rozmiar ARG_MAX?
Będzie to zależeć od wartości ARG_MAX, która może zmieniać się między systemami. Aby znaleźć wartość dla uruchomienia systemu (pokazując wynik na moim jako przykład):
$ getconf ARG_MAX
2097152
Nie ma to nic wspólnego z cp
twoją powłoką, jest to limit narzucony przez jądro, nie będzie wykonywał exec()
poleceń ( ), jeśli ich argumenty są dłuższe niż ARG_MAX
. Jeśli więc podana przez ciebie długość listy argumentów cp
jest większa niż ARG_MAX, cp
polecenie w ogóle się nie uruchomi.
Aby odpowiedzieć na główne pytanie, nie cp
będzie przetwarzał żadnych plików, ponieważ nigdy nie zostanie wykonany z tyloma argumentami. Powinienem również wspomnieć, że nie zależy to od liczby argumentów, ale od ich długości. Możliwe, że masz ten sam problem z bardzo nielicznymi, ale bardzo długimi nazwami plików.
Aby obejść te błędy, uruchom polecenie w pętli:
for file in /src/*; do cp "$file" /dst/; done
C
mogą mieć problemy z ARG_MAX i naprawdę długie nazwy plików?
IFS="\n" for file in /src/*; do mv "$file" /dst/; done
Lubrsync -a /src/ /dst/
.