CP: максимальное количество исходных файлов аргументов для утилиты копирования


11

Учтите, что в / src / находится бесчисленное количество файлов

cp /src/* /dst/

Сколько файлов cpбудет успешно обработано?


2
Если список аргументов слишком длинный (помните, что * расширяет до списка всех файлов, которые соответствуют глобусу), вы можете обойти его, используя eg IFS="\n" for file in /src/*; do mv "$file" /dst/; doneили rsync -a /src/ /dst/.
DopeGhoti

Ответы:


18

Это сильно зависит от системы и версии, количества и размера аргументов, а также от количества и размера имен переменных среды.

Традиционно в Unix ограничение (как сообщалось getconf ARG_MAX) было более или менее на совокупный размер:

  • Длина строки аргумента (включая завершающую '\0')
  • Длина массива указателей на эти строки, поэтому обычно 8 байтов на аргумент в 64-битной системе
  • Длина строк окружения (включая завершающую '\0'), при этом строка окружения условно выглядит примерно так var=value.
  • Длина массива указателей на эти строки, поэтому обычно 8 байтов на аргумент в 64-битной системе

Принимая во внимание, что это 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?
Сергей Колодяжный

14

Это будет зависеть от значения 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 и действительно длинными именами файлов?
Гарольд Фишер
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.