Linux

Слишком длинный список аргументов: ошибка для команд rm, cp, mv

У меня есть несколько сотен PDF-файлов в каталоге в UNIX. Имена PDF-файлов очень длинные (около 60 символов).

Когда я пытаюсь удалить все PDF-файлы вместе с помощью следующей команды:

rm -f *.pdf

 

я получаю такую ошибку:

/bin/rm: cannot execute [Argument list too long].

 

Каково решение этой проблемы? Возникает ли эта ошибка для команд mv и cp? Если да, то как решить эту проблему для этих команд?

 

Ответ 1

Это происходит потому, что bash фактически расширяет звездочку до каждого подходящего файла, создавая очень длинную командную строку.

Попробуйте это:

find . -name "*.pdf" -print0 | xargs -0 rm

 

 

Внимание: это рекурсивный поиск, и он найдет (и удалит) файлы и в подкаталогах. Добавляйте -f к команде rm, только если вы уверены, что вам не нужно подтверждение.Чтобы сделать команду нерекурсивной, можно сделать следующее:

find . -maxdepth 1 -name "*.pdf" -print0 | xargs -0 rm

 

Другой вариант — использовать флаг find -delete:

find . -name "*.pdf" -delete

 

Ответ 2

Это ограничение ядра на размер аргумента командной строки. Вместо этого используйте цикл for.

Происхождение проблемы

Это системная проблема, связанная с execve и константой ARG_MAX. Об этом есть много документации (см. man execve, debian's wiki). По сути, расширение выдает команду (с ее параметрами), которая превышает предел ARG_MAX. В ядре 2.6.23 этот предел был установлен на уровне 128 кБ. Эта константа была увеличена, и вы можете получить ее значение, выполнив:

getconf ARG_MAX

# 2097152 # on 3.5.0-40-generic

Решение: Использование цикла for

 

Используйте цикл for, так как он рекомендован в BashFAQ/095 и нет никаких ограничений, кроме пространства оперативной/памяти. Проведите пробный запуск, чтобы убедиться, что он удалит то, что вы ожидаете:

for f in *.pdf; do echo rm "$f"; done

 

И выполните его:

for f in *.pdf; do rm "$f"; done

 

Также это переносимый подход, так как glob имеет сильное и устойчивое поведение среди оболочек (часть спецификации POSIX).

Замечание: Этот способ действительно медленнее, но он более удобен в обслуживании, поскольку может адаптировать более сложные сценарии, например, когда нужно выполнить более одного действия.

Решение: Использование find

Если вы настаиваете, вы можете использовать find, но, на самом деле, не используйте xargs, поскольку он «опасен при чтении не NUL-разделенного ввода»:

find . -maxdepth 1 -name '*.pdf' -delete 

 

Использование -maxdepth 1 ... -delete вместо -exec rm {} + позволяет find просто выполнить необходимые системные вызовы самостоятельно, не используя внешний процесс, следовательно, быстрее.

 

Ответ 3

Если вы пытаетесь удалить очень большое количество файлов за один раз, вы, вероятно, столкнетесь с этой ошибкой:

/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

Схожие статьи

Linux

Linux API для отображения запущенных процессов

Linux

Как примонтировать диск в Linux. Пошаговое руководство

Linux

Защита SuperMicro IPMI BMC

Linux

Как определить объем использованной памяти и среднюю нагрузку на Linux-сервере?

×