Ответы:
Это сильно зависит от системы и версии, количества и размера аргументов, а также от количества и размера имен переменных среды.
Традиционно в Unix ограничение (как сообщалось getconf ARG_MAX
) было более или менее на совокупный размер:
'\0'
)'\0'
), при этом строка окружения условно выглядит примерно так var=value
.Принимая во внимание, что это cp
также считается аргументом (это первый аргумент).
В Linux это зависит от версии. Поведение там изменилось недавно, когда это уже не фиксированное пространство.
При проверке в Linux 3.11 getconf ARG_MAX
теперь сообщается о четверти ограничения, установленного для размера стека, или 128 кБ, если это меньше 512 кБ).
( 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
Теперь это не значит, что вы можете передать 1 миллион пустых аргументов. В 64-битной системе 1 миллион пустых аргументов составляет список указателей размером 8 МБ, что превышает размер моего стека в 4 МБ.
$ IFS=:; /bin/true ${=${(l.1000000..:.)${:-}}}
zsh: killed /bin/true ${=${(l.1000000..:.)${:-}}}
(Вы заметите, что это не ошибка E2BIG. Я не уверен, в какой момент процесс там будет убит, хотя, если это в execve
системном вызове или позже).
Также обратите внимание (все еще в Linux 3.11), что максимальный размер одного аргумента или строки среды составляет 128 кБ, независимо от размера стека.
$ /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
номеру? то есть как вы рассчитали, что последовательность будет меньше 2097152
размера ARG_MAX?
Это будет зависеть от значения ARG_MAX, которое может меняться в разных системах. Чтобы узнать значение для запуска вашей системы (в качестве примера показан мой результат):
$ getconf ARG_MAX
2097152
Это не имеет ничего общего с cp
вашей оболочкой, это ограничение, налагаемое ядром, оно не будет выполнять exec()
команды ( ), если их аргументы длиннее, чем ARG_MAX
. Таким образом, если длина списка аргументов, который вы cp
указали, превышает ARG_MAX, cp
команда вообще не будет выполняться.
Чтобы ответить на ваш главный вопрос, не cp
будет обрабатывать файлы, так как он никогда не будет выполнен с таким количеством аргументов. Я должен также упомянуть, что это зависит не от количества аргументов, а от их длины. Вы можете предположить, что такая же проблема возникает с очень небольшим, но очень длинным именем файла.
Способ обойти эти ошибки - запустить вашу команду в цикле:
for file in /src/*; do cp "$file" /dst/; done
C
могут иметь проблемы с ARG_MAX и действительно длинными именами файлов?
IFS="\n" for file in /src/*; do mv "$file" /dst/; done
илиrsync -a /src/ /dst/
.