Я использую следующую команду:
\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: слишком длинный список аргументов
Любые идеи?
* .jpg расширяется до списка длиннее, чем может обработать оболочка. Попробуйте вместо этого
find /home/ftpuser/public_html/ftparea/ -name "*.jpg" -exec cp -uf "{}" /your/destination \;
Существует максимальный предел длины списка аргументов для системных команд - это ограничение зависит от дистрибутива и зависит от значения параметра MAX_ARG_PAGES
когда ядро скомпилировано, и не может быть изменено без перекомпиляции ядра.
Из-за того, как глобализация обрабатывается оболочкой, это повлияет на большинство системных команд, если вы используете один и тот же аргумент ("* .jpg"). Поскольку глобус сначала обрабатывается оболочкой, а затем отправляется команде, команда:
cp -uf *.jpg /targetdir/
по сути, то же самое для оболочки, как если бы вы написали:
cp -uf 1.jpg 2.jpg ... n-1.jpg n.jpg /targetdir/
Если вы имеете дело с большим количеством jpeg-файлов, это может очень быстро стать неуправляемым. В зависимости от вашего соглашения об именах и количества файлов, которые вам действительно нужно обработать, вы можете запустить cp команда для другого подмножества каталога за раз:
cp -uf /sourcedir/[a-m]*.jpg /targetdir/
cp -uf /sourcedir/[n-z]*.jpg /targetdir/
Это может сработать, но насколько эффективно это будет, зависит от того, насколько хорошо вы можете разбить список файлов на удобные глобализируемые блоки.
Подключаемый. Мне нравится это слово.
Некоторые команды, например найти и xargs, может обрабатывать большие списки файлов, не создавая списков аргументов слишком большого размера.
find /sourcedir/ -name '*.jpg' -exec cp -uf {} /targetdir/ \;
Аргумент -exec запускает оставшуюся часть командной строки один раз для каждого файла, найденного найти, заменяя {} каждым найденным именем файла. Поскольку cp команда запускается только для одного файла за раз, ограничение списка аргументов не является проблемой.
Это может быть медленным из-за необходимости обрабатывать каждый файл отдельно. С помощью xargs может предоставить более эффективное решение:
find /sourcedir/ -name '*.jpg' -print0 | xargs -0 cp -uf -t /destdir/
xargs может взять полный список файлов, предоставленный найти, и разбейте его на списки аргументов управляемого размера и запустите cp в каждом из этих подсписок.
Конечно, также есть возможность просто перекомпилировать ядро, установив большее значение для MAX_ARG_PAGES
. Но перекомпиляция ядра - это больше работы, чем я хочу объяснить в этом ответе.
Это происходит потому, что ваше выражение с подстановочными знаками (*.jpg
) превышает ограничение длины аргумента командной строки при раскрытии (вероятно, потому что у вас много файлов .jpg в /home/ftpuser/public_html/ftparea
).
Есть несколько способов обойти это ограничение, например, используя find
или xargs
. Посмотри на Эта статья для получения более подробной информации о том, как это сделать.
Как прокомментировал GoldPseudo, существует ограничение на количество аргументов, которые вы можете передать процессу, который вы создаете. См. Его ответ для хорошего описания этого параметра.
Вы можете избежать проблемы, либо не передавая процессу слишком много аргументов, либо уменьшив количество передаваемых вами аргументов.
Цикл for в оболочке, find и ls, grep и цикл while делают то же самое в этой ситуации:
for file in /path/to/directory/*.jpg ;
do
rm "$file"
done
и
find /path/to/directory/ -name '*.jpg' -exec rm {} \;
и
ls /path/to/directory/ |
grep "\.jpg$" |
while
read file
do
rm "$file"
done
у всех есть одна программа, которая читает каталог (сама оболочка, find и ls), и другая программа, которая фактически принимает один аргумент на выполнение и перебирает весь список команд.
Теперь это будет медленным, потому что rm нужно разветвлять и запускать для каждого файла, который соответствует шаблону * .jpg.
Здесь в игру вступает xargs. xargs принимает стандартный ввод и для каждых N (для freebsd по умолчанию 5000) строк порождает одну программу с N аргументами. xargs - это оптимизация вышеупомянутых циклов, потому что вам нужно только разветвлять программы 1 / N для перебора всего набора файлов, которые считывают аргументы из командной строки.
Для программы можно указать максимальное количество аргументов, bash расширяет * .jpg до множества аргументов для cp. Вы можете решить эту проблему с помощью find, xargs или rsync и т. Д.
Посмотрите здесь о xargs и найдите
Значок '*' расширяется до слишком большого количества имен файлов. Вместо этого используйте find / home / ftpuser / public_html -name '* .jpg'.
Используя +
возможность find -exec
значительно ускорит операцию.
find /home/ftpuser/public_html/ftparea/ -name "*jpg" -exec cp -uf -t /your/destination "{}" +
В +
вариант требует {}
быть последним аргументом, поэтому, используя -t /your/destination
(или --target-directory=/your/destination
) вариант cp
заставляет это работать.
Из man find
:
-exec команда {} +
This variant of the -exec action runs the specified command on the selected files, but the command line is built by appending each selected file name at the end; the total number of invoca‐ tions of the command will be much less than the number of matched files. The command line is built in much the same way that xargs builds its command lines. Only one instance of ‘{}’ is allowed within the command. The command is executed in the starting directory.
редактировать: аргументы переставлены в cp
Похоже, у вас слишком много *.jpg
файлы в этом каталоге, чтобы сразу поместить их все в командную строку. Вы можете попробовать:
find /home/ftpuser/public_html/ftparea1 -name '*.jpg' | xargs -I {} cp -uf {} /home/ftpuser/public_html/ftparea2/
Вам может потребоваться проверить man xargs
для вашей реализации, чтобы увидеть, -I
переключатель подходит для вашей системы.
Собственно, вы действительно собираетесь скопировать эти файлы в то же место, где они уже находятся?
Перейти в папку
cd /home/ftpuser1/public_html/
и выполните следующее:
cp -R ftparea/ /home/ftpuser2/public_html/
Таким образом, если в папке ftparea есть подпапки, это может иметь негативный эффект, если вы хотите, чтобы из нее были только файлы * .jpg, но если вложенных папок нет, этот подход определенно будет намного быстрее, чем используя find и xargs