CP: maksymalna liczba argumentów liczby plików źródłowych dla narzędzia kopiowania

11

Weź pod uwagę, że w katalogu / src / znajduje się niezliczona liczba plików

cp /src/* /dst/

Ile plików cpuda się przetworzyć?

Mikrofon
źródło
2
Jeśli lista argumentów jest zbyt długa (pamiętaj, że * rozwija się do listy wszystkich plików, które pasują do globu), możesz obejść ją używając np . IFS="\n" for file in /src/*; do mv "$file" /dst/; doneLub rsync -a /src/ /dst/.
DopeGhoti

Odpowiedzi:

18

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:

  • Długość ciągów argumentów (łącznie z zakończeniem '\0')
  • Długość tablicy wskaźników do tych ciągów, czyli zazwyczaj 8 bajtów na argument w systemie 64-bitowym
  • Długość ciągów środowiska (łącznie z zakończeniem '\0'), przy czym ciąg znaków środowiska jest umownie podobny var=value.
  • Długość tablicy wskaźników do tych ciągów, czyli zazwyczaj 8 bajtów na argument w systemie 64-bitowym

Pamiętając, że cpró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_MAXpokazuje teraz jedną czwartą limitu ustawionego na stosie lub 128 kB, jeśli jest to mniej niż 512 kB.

( zshskł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 execvewywoł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
Stéphane Chazelas
źródło
Czy możesz się podzielić, jak wymyśliłeś 164686numer? tj. jak obliczyłeś, że sekwencja będzie 2097152mniejsza niż rozmiar ARG_MAX?
Sergiy Kolodyazhnyy
14

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 cptwoją 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 cpjest większa niż ARG_MAX, cppolecenie w ogóle się nie uruchomi.

Aby odpowiedzieć na główne pytanie, nie cpbę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
terdon
źródło
Czy to oznacza, że ​​nawet języki niższego poziomu Cmogą mieć problemy z ARG_MAX i naprawdę długie nazwy plików?
Harold Fischer