Ошибка "Слишком длинный список аргументов" для команд rm, cp, mv
У меня есть несколько сотен PDF-файлов в директории на UNIX. Имена этих PDF-файлов довольно длинные (примерно 60 символов).
Когда я пытаюсь удалить все PDF-файлы сразу, используя следующую команду:
rm -f *.pdf
я получаю следующую ошибку:
/bin/rm: cannot execute [Argument list too long]
Какова причина этой ошибки и какое возможное решение?
Происходит ли эта ошибка также при использовании команд mv
и cp
? Если да, то как решить эту проблему для этих команд?
5 ответ(ов)
Причина, по которой это происходит, заключается в том, что bash фактически развивает звездочку (*) в каждый соответствующий файл, в результате чего получается очень длинная командная строка.
Попробуйте следующее:
find . -name "*.pdf" -print0 | xargs -0 rm
Внимание: это рекурсивный поиск, и он найдет (и удалит) файлы в подкаталогах. Добавьте флаг -f
к команде rm только если уверены, что не хотите подтверждения.
Чтобы сделать команду нерекурсивной, используйте:
find . -maxdepth 1 -name "*.pdf" -print0 | xargs -0 rm
Еще один вариант — использовать флаг -delete
у find:
find . -name "*.pdf" -delete
Чтобы удалить файлы с расширением .pdf
из текущей директории, вы можете использовать команду find
с действием -delete
. Например, следующая команда:
find . -maxdepth 1 -name '*.pdf' -delete
В этом случае:
.
указывает, что поиск осуществляется в текущей директории.-maxdepth 1
ограничивает поиск только текущим уровнем, не затрагивая подкаталоги.-name '*.pdf'
находит файлы, имя которых соответствует шаблону*.pdf
.-delete
удаляет найденные файлы.
Обратите внимание, что команда -delete
не запрашивает подтверждения, поэтому будьте осторожны при её использовании, чтобы избежать случайного удаления нужных файлов.
Для тех, у кого нет времени: выполните следующую команду в терминале:
ulimit -S -s unlimited
После этого выполните операции cp
, mv
или rm
.
Еще один способ — заставить xargs
обрабатывать команды партиями. Например, чтобы удалить файлы по 100 штук за раз, перейдите в нужный каталог и выполните следующую команду:
echo *.pdf | xargs -n 100 rm
Таким образом, команда rm
будет вызываться для группы из 100 файлов формата .pdf
за один раз, что может быть полезно для повышения производительности при работе с большим количеством файлов.
Если вы пытаетесь удалить очень большое количество файлов одновременно (например, я удалял каталог с более чем 485,000 файлами), вы, вероятно, столкнетесь с ошибкой:
/bin/rm: Argument list too long.
Проблема заключается в том, что когда вы вводите что-то вроде rm -rf *
, символ *
заменяется списком всех соответствующих файлов, например, на “rm -rf file1 file2 file3 file4” и так далее. Существует относительно небольшой буфер памяти, выделенный для хранения этого списка аргументов, и если он заполняется, оболочка не выполнит программу.
Чтобы обойти эту проблему, многие используют команду find
, которая находит каждый файл и передает его по одному команде rm
, например:
find . -type f -exec rm -v {} \;
Однако, столкнувшись с необходимостью удалить 500,000 файлов, я заметил, что это занимает слишком много времени.
Я наткнулся на гораздо более быстрый способ удаления файлов – команда find
имеет встроенный ключ -delete
. Вот что я в итоге использовал:
find . -type f -delete
Используя этот метод, я удалял файлы со скоростью около 2000 файлов в секунду – намного быстрее!
Вы также можете выводить имена файлов, когда они удаляются:
find . -type f -print -delete
…или даже показать, сколько файлов будет удалено, а затем замерить, сколько времени требуется для их удаления:
root@devel# ls -1 | wc -l && time find . -type f -delete
100000
real 0m3.660s
user 0m0.036s
sys 0m0.552s
Как изменить цвет вывода echo в Linux
Как перенаправить вывод в файл и на экран (stdout)
Как сделать паузу в shell-скрипте на одну секунду перед продолжением?
Как работает "cat << EOF" в bash?
Как использовать 'grep' для непрерывного потока?