Я использую следующую команду:
\cp -uf /home/ftpuser1/public_html/ftparea/*.jpg /home/ftpuser2/public_html/ftparea/
И я получаю ошибку:
-bash: /bin/cp: Argument list too long
Я также попробовал:
ls /home/ftpuser1/public_html/ftparea/*.jpg | xargs -I {} cp -uf {} /home/ftpuser2/public_html/ftparea/
Все еще есть -bash: / bin / ls: список аргументов слишком длинный
Есть идеи?
linux
bash
unix-shell
icelizard
источник
источник
ls
не предназначен для такого рода вещей. Использованиеfind
.ls
это особенно не предназначены для этого: mywiki.wooledge.org/ParsingLsОтветы:
* .jpg расширяется до списка длиннее, чем может обработать оболочка. Попробуйте это вместо
источник
Существует максимальный предел длины списка аргументов для системных команд - этот предел зависит от дистрибутива в зависимости от значения
MAX_ARG_PAGES
времени компиляции ядра и не может быть изменен без перекомпиляции ядра.Из-за того, как оболочка обрабатывает глобирование, это повлияет на большинство системных команд, когда вы используете один и тот же аргумент ("* .jpg"). Поскольку глоб обрабатывается сначала оболочкой, а затем отправляется команде, команда:
по сути то же самое для оболочки, как если бы вы написали:
Если вы имеете дело с большим количеством JPEG, это может стать неуправляемым очень быстро. В зависимости от вашего соглашения об именах и количества файлов, которые вы фактически должны обработать, вы можете одновременно запускать команду cp в другом подмножестве каталога:
Это может сработать, но как именно это будет эффективно, зависит от того, насколько хорошо вы сможете разбить ваш список файлов на удобные блоки, которые можно сгладить.
Globbable. Мне нравится это слово.
Некоторые команды, такие как find и xargs , могут обрабатывать большие списки файлов, не создавая списков аргументов очень большого размера.
Аргумент -exec будет запускать оставшуюся часть командной строки один раз для каждого файла, найденного командой find , заменяя {} на каждое найденное имя файла. Поскольку команда cp выполняется только для одного файла за раз, ограничение списка аргументов не является проблемой.
Это может быть медленным из-за необходимости обрабатывать каждый файл отдельно. Использование xargs может обеспечить более эффективное решение:
xargs может взять полный список файлов, предоставленный командой find , и разбить его на списки аргументов управляемых размеров и запустить cp для каждого из этих подсписков.
Конечно, есть также возможность просто перекомпилировать ядро, установив большее значение для
MAX_ARG_PAGES
. Но перекомпиляция ядра - это больше работы, чем я хочу объяснить в этом ответе.источник
xargs
кажется гораздо более эффективным, так как итоговое количество командных вызовов намного меньше. В моем случае я вижу в 6-12 раз лучшую производительность при использовании,args
чем когда-exec
решение с ростом числа файлов повышает эффективность.Это происходит потому, что ваше подстановочное выражение (
*.jpg
) превышает предел длины аргумента командной строки при расширении (возможно, потому что у вас много файлов .jpg в/home/ftpuser/public_html/ftparea
).Есть несколько способов обойти это ограничение, например использование
find
илиxargs
. Посмотрите на эту статью для получения более подробной информации о том, как это сделать.источник
Как прокомментировал GoldPseudo, существует ограничение на количество аргументов, которые вы можете передать процессу, который вы порождаете. Смотрите его ответ для хорошего описания этого параметра.
Вы можете избежать этой проблемы, не передавая процессу слишком много аргументов, или уменьшив количество передаваемых аргументов.
Цикл for в оболочке find и ls, grep и цикл while в этой ситуации делают одно и то же:
и
и
у всех есть одна программа, которая читает каталог (сама оболочка, find и ls), и другая программа, которая фактически принимает один аргумент за выполнение и выполняет итерацию по всему списку команд.
Теперь это будет медленным, потому что rm нужно разветвлять и выполнять для каждого файла, который соответствует шаблону * .jpg.
Это где Xargs вступает в игру. xargs принимает стандартный ввод и для каждой N (для freebsd по умолчанию 5000) строк она порождает одну программу с N аргументами. xargs - это оптимизация вышеуказанных циклов, потому что вам нужно только разветвить программы 1 / N, чтобы перебрать весь набор файлов, которые читают аргументы из командной строки.
источник
В программе может быть указано максимальное количество аргументов, bash расширяет * .jpg до множества аргументов для cp. Вы можете решить это, используя find, xargs или rsync и т. Д.
Посмотрите здесь про Xargs и найдите
/programming/143171/how-can-i-use-xargs-to-copy-files-that-have-spaces-and-quotes-in-their-names
источник
Глобус * расширяется до слишком большого количества имен файлов. Вместо этого используйте find / home / ftpuser / public_html -name '* .jpg'.
источник
Использование
+
опцииfind -exec
значительно ускорит работу.+
Вариант требует ,{}
чтобы быть последним аргументом поэтому использование-t /your/destination
(или--target-directory=/your/destination
) опцииcp
делает его работу.От
man find
:Изменить : переставить аргументы в cp
источник
cp
чтобы исправить эту ошибку.Похоже, у вас слишком много
*.jpg
файлов в этом каталоге, чтобы поместить их все в командную строку одновременно. Вы можете попробовать:Возможно, вам придется проверить
man xargs
свою реализацию, чтобы убедиться, что-I
коммутатор подходит для вашей системы.На самом деле, вы действительно собираетесь скопировать эти файлы в то же место, где они уже находятся?
источник
ls
возникнет такая же проблема! Я изменился наfind
что не будет.Перейти в папку
и выполните следующее:
Таким образом, если в папке «ftparea» есть подпапки, это может иметь негативные последствия, если вы хотите, чтобы из нее были только файлы «* .jpg», но если нет подпапок, этот подход определенно будет намного быстрее, чем используя find и xargs
источник