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

Лучшие нативные и консольные игры для Linux, какие из них на нее идут

Linux

Как настроить рабочий стол XFCE? Настройка рабочего окружения XFCE

Linux

Как быстро скопировать большое количество файлов между двумя серверами

Linux

Как часто следует перезагружать серверы Linux?