У меня есть несколько сотен PDF-файлов в каталоге в UNIX. Названия PDF-файлов действительно длинные (около 60 символов).
Когда я пытаюсь удалить все PDF-файлы вместе, используя следующую команду:
rm -f *.pdf
Я получаю следующую ошибку:
/bin/rm: cannot execute [Argument list too long]
Каково решение этой ошибки? Возникает ли эта ошибка для mv
и cp
команды, а? Если да, как решить для этих команд?
Ответы:
Причина этого заключается в том, что bash фактически расширяет звездочку до каждого соответствующего файла, создавая очень длинную командную строку.
Попробуй это:
Предупреждение: это рекурсивный поиск, который также найдет (и удалит) файлы в подкаталогах. Придерживайтесь
-f
команды rm, только если вы уверены, что не хотите подтверждения.Чтобы сделать команду нерекурсивной, вы можете сделать следующее:
Другой вариант - использовать
-delete
флаг поиска :источник
xargs
специально разбивает список и при необходимости выдает несколько команд.-maxdepth 1
должен быть первым аргументом после пути.-delete
флаг для удаления файлов, которые он находит, и даже если бы он этого не сделал, все равно было бы лучше использовать-exec
для выполнения rm, чем вызывать xargs (который теперь представляет собой 3 процесса и конвейер вместо одного процесса с-delete
или 2 процесса с-exec
).dangerous (broken, exploitable, etc.)
, это довольно смешно. Несомненно, вы должны быть осторожны при использованииxargs
, но это не совсем такeval/evil
.-exec
вызовеrm
число процессов будет равно 1 + количество файлов, хотя число одновременных процессов из этого может быть 2 (возможно, find выполнит процессы rm одновременно). Количество используемых процессовxargs
будет значительно сокращено до 2 + n, где n - это некоторое число процессов, которое меньше количества файлов (скажем, число файлов / 10, хотя, вероятно, больше в зависимости от длины путей). Предполагая, что find выполняет удаление напрямую, использование-delete
должно быть единственным процессом, который будет вызван.ТЛ; др
Это ограничение ядра на размер аргумента командной строки.
for
Вместо этого используйте цикл.Происхождение проблемы
Это системная проблема, связанная
execve
иARG_MAX
постоянная. Об этом много документации (см. Man execve , вики Debian ).По сути, расширение создает команду (с ее параметрами), которая превышает
ARG_MAX
предел. На ядре2.6.23
ограничение было установлено на128 kB
. Эта константа была увеличена, и вы можете получить ее значение, выполнив:Решение: использование
for
LoopИспользуйте
for
цикл, как это рекомендуется для BashFAQ / 095, и нет никаких ограничений, за исключением объема ОЗУ / памяти:Пробный запуск, чтобы убедиться, что он удалит то, что вы ожидаете:
И выполнить это:
Также это переносимый подход, поскольку у glob сильное и согласованное поведение среди оболочек ( часть спецификации POSIX ).
Примечание. Как отмечается в нескольких комментариях, это действительно медленнее, но более приемлемо, поскольку может адаптировать более сложные сценарии, например, когда требуется выполнить больше, чем одно действие.
Решение: Использование
find
Если вы настаиваете, вы можете использовать,
find
но на самом деле не используйте xargs, поскольку он «опасен (сломан, может использоваться и т. Д.) При чтении ввода, не разделенного NUL» :Использование
-maxdepth 1 ... -delete
вместо-exec rm {} +
позволяетfind
просто выполнять необходимые системные вызовы без использования внешнего процесса, следовательно, быстрее (благодаря комментарию @chepner ).Ссылки
источник
for
петли. Я использовалfind
раньше, но я всегда ищу, как это сделать, потому что я все время забываю варианты и т. Д.for
Кажется, легче вспомнить ИМХОfor f in *; do rm "$f"; done
работу как очарованиеfind -exec
Решение представляется гораздо быстрее , чемfor
цикл.4.15.0-1019-gcp
если быть точным), и предел все еще в 2097152. Интересно, что поиск ARG_MAX в git-репозитории linux дает результат, показывающий, что ARG_MAX находится в 131702.find
имеет-delete
действие:источник
xargs
, согласно ответу Денниса, работает как задумано.-exec
является удаление нескольких файлов.-exec rm {} +
будет делать то же самое, но все еще требует запуска хотя бы одного внешнего процесса.-delete
позволяетfind
просто выполнить необходимые системные вызовы самостоятельно, без использования внешней оболочки.Другой ответ состоит в том, чтобы заставить
xargs
обрабатывать команды в пакетном режиме. Например, кdelete
файлам100
за раз,cd
в каталог и запустите это:echo *.pdf | xargs -n 100 rm
источник
echo
встроена оболочка. Если вы в конечном итоге используете командуecho
, вы все равно столкнетесь с ограничением аргументов программы.Или вы можете попробовать:
источник
find . -maxdepth 1 -name '*.pdf' -exec rm -f {} \;
Если вы пытаетесь удалить очень большое количество файлов за один раз (сегодня я удалил каталог с 485 000+), вы, вероятно, столкнетесь с этой ошибкой:
Проблема заключается в том, что когда вы набираете что-то вроде
rm -rf *
, то*
заменяется списком каждого соответствующего файла, например, «rm -rf file1 file2 file3 file4» и так далее. Для хранения этого списка аргументов имеется относительно небольшой буфер памяти, и, если он заполнен, оболочка не выполнит программу.Чтобы обойти эту проблему, многие люди используют команду find, чтобы найти каждый файл и передать их один за другим команде «rm», например так:
Моя проблема в том, что мне нужно было удалить 500 000 файлов, и это заняло слишком много времени.
Я наткнулся на гораздо более быстрый способ удаления файлов - команда «find» имеет встроенный флаг «-delete»! Вот что я в итоге использовал:
Используя этот метод, я удалял файлы со скоростью около 2000 файлов в секунду - намного быстрее!
Вы также можете показать имена файлов при их удалении:
... или даже показать, сколько файлов будет удалено, а затем время, необходимое для их удаления:
источник
sudo find . -type f -delete
чтобы удалить около 485 тысяч файлов, и это сработало для меня. Прошло около 20 секунд.Вы можете попробовать это:
РЕДАКТИРОВАТЬ: комментарий ThiefMaster предлагает мне не раскрывать такую опасную практику для джедаев молодой оболочки, поэтому я добавлю более «более безопасную» версию (ради сохранения вещей, когда у кого-то есть файл «-rf. ..Pdf»)
После запуска вышеприведенного, просто откройте файл /tmp/dummy.sh в вашем фаворе. редактировать и проверять каждую строку на наличие опасных имен файлов, комментируя их, если они найдены.
Затем скопируйте скрипт dummy.sh в ваш рабочий каталог и запустите его.
Все это по соображениям безопасности.
источник
-rf .. .pdf
-rf
имеет приоритет над-i
вашей второй версией (без ручной проверки). И в принципе бесполезно для массового удаления, потому что подсказки для каждого файла.Вы можете использовать массив bash:
Таким образом, он будет стирать партиями по 1000 файлов за шаг.
источник
Вы можете использовать эту похвалу
источник
У команды rm есть ограничение на количество файлов, которые вы можете удалить одновременно.
Одна возможность, вы можете удалить их, используя несколько раз команды rm, основанные на ваших шаблонах файлов, например:
Вы также можете удалить их с помощью команды find :
источник
rm
не имеет такого ограничения на количество файлов, которые он будет обрабатывать (кроме этого онargc
не может быть больше, чемINT_MAX
). Это ограничение ядра на максимальный размер всего массива аргументов (поэтому длина имен файлов значительна).Если это имена файлов с пробелами или специальными символами, используйте:
Это предложение ищет все файлы в текущем каталоге (-maxdepth 1) с расширением pdf (-name '* .pdf'), а затем удаляет каждый из них (-exec rm "{}").
Выражение {} заменяет имя файла, а "{}" задает имя файла в виде строки, включая пробелы или специальные символы.
источник
-exec
том, что вы не вызываете оболочку. Цитаты здесь не делают абсолютно ничего полезного. (Они предотвращают любое расширение подстановочного знака и разбиение токена на строке в оболочке, в которой вы вводите эту команду, но строка{}
не содержит пробельных символов или символов подстановки оболочки.)я столкнулся с той же проблемой при копировании исходного каталога формы в место назначения
исходный каталог имел файлы ~ 3 lakcs
я использовал cp с опцией -r, и это сработало для меня
cp -r abc / def /
он скопирует все файлы из abc в def без предупреждения о слишком длинном списке аргументов
источник
Попробуйте это также. Если вы хотите удалить файлы / папки за 30/90 (+) или менее 30/90 (-) дней, вы можете использовать приведенные ниже команды ex
Пример: для 90 дней исключается выше после 90 дней удаления файлов / папок, это означает 91,92 .... 100 дней
Пример: только для последних 30-дневных файлов, которые вы хотите удалить, используйте команду ниже (-)
Если вы хотите посмотреть файлы более чем на 2 дня
Если вы хотите видеть файлы / папки только за последний месяц. Пример:
Более 30 дней больше, чем только список файлов / папок. Например:
источник
Я удивлен, что здесь нет
ulimit
ответов. Каждый раз, когда у меня возникает эта проблема, я оказываюсь здесь или здесь . Я понимаю, что это решение имеет ограничения, но,ulimit -s 65536
похоже, часто помогает мне.источник
У меня была та же проблема с папкой, полной временных изображений, которая росла день ото дня, и эта команда помогла мне очистить папку
Разница с другими командами заключается в параметре mtime, который будет принимать только файлы старше X дней (в примере 50 дней)
Используя это несколько раз, уменьшая при каждом выполнении дневной диапазон, я смог удалить все ненужные файлы
источник
Я знаю только способ обойти это. Идея состоит в том, чтобы экспортировать этот список файлов PDF в ваш файл. Затем разделите этот файл на несколько частей. Затем удалите файлы PDF, перечисленные в каждой части.
wc -l - подсчитать, сколько строк содержит list.txt. Когда у вас есть представление о том, как долго это происходит, вы можете разделить его пополам, вперёд или что-то в этом роде. Использование команды split -l Например, разбить его на 600 строк каждая.
это создаст несколько файлов с именами xaa, xab, xac и т. д., в зависимости от того, как вы разделите его. Теперь, чтобы «импортировать» каждый список в этом файле в команду rm, используйте это:
Извините за мой плохой английский.
источник
pdf_format_sucks.docx
он также будет удален ... ;-) Вы должны использовать правильное и точное регулярное выражение при подборе файлов pdf.still_pdf_format_sucks.docx
будет удалено. Точка.
в".pdf"
регулярном выражении соответствует любому символу. Я бы предложил"[.]pdf$"
вместо.pdf
.Я столкнулся с этой проблемой несколько раз. Многие решения будут запускать
rm
команду для каждого отдельного файла, который необходимо удалить. Это очень неэффективно:В итоге я написал скрипт на python для удаления файлов на основе первых 4 символов в имени файла:
Это сработало очень хорошо для меня. Мне удалось очистить более 2 миллионов временных файлов в папке примерно за 15 минут. Я прокомментировал tar из небольшого фрагмента кода, чтобы любой, кто имеет минимальные знания Python или не обладал ими, мог манипулировать этим кодом.
источник
И еще один:
printf
это встроенная оболочка, и, насколько я знаю, она всегда была таковой. Теперь, учитывая, чтоprintf
это не команда оболочки (а встроенная), она не подвержена "argument list too long ...
" фатальной ошибке.Таким образом, мы можем безопасно использовать его с шаблонами сглаживания оболочки, такими как
*.[Pp][Dd][Ff]
, затем передаем по выводу ееrm
команду remove ( ),xargs
которая проверяет, соответствует ли она достаточному количеству имен файлов в командной строке, чтобы не пропуститьrm
команду, являющуюся оболочкой. команда.Оператор
\0
inprintf
служит пустым разделителем для имен файлов, которые затем обрабатываютсяxargs
командой с использованием it (-0
) в качестве разделителя, поэтомуrm
он не завершается ошибкой, если в именах файлов есть пробелы или другие специальные символы.источник
printf
не встроенная оболочка, на нее распространяются те же ограничения.Вы можете создать временную папку, переместить все файлы и подпапки, которые вы хотите сохранить, во временную папку, затем удалить старую папку и переименовать временную папку в старую папку, попробуйте этот пример, пока вы не будете уверены, что все это работает:
rm -r big_folder
не будут удалены все файлы вbig_folder
независимо от того , сколько. Вы просто должны быть очень осторожны, у вас сначала есть все файлы / папки, которые вы хотите сохранить, в данном случае это былоfile1.pdf
источник
Удалить все
*.pdf
в каталоге/path/to/dir_with_pdf_files/
Удаление определенных файлов с
rsync
помощью подстановочного знака, вероятно, является самым быстрым решением, если у вас миллионы файлов. И это позаботится об ошибке, которую вы получаете.(Необязательный шаг): DRY RUN. Чтобы проверить, что будет удалено без удаления. `
, , ,
Нажмите rsync советы и хитрости для более rsync хаков
источник
Я обнаружил, что для очень больших списков файлов (> 1e6) эти ответы были слишком медленными. Вот решение с использованием параллельной обработки в Python. Я знаю, я знаю, что это не Linux ... но ничего другого здесь не работает.
(Это спасло меня часы)
источник
Я столкнулся с подобной проблемой, когда приложение создавало миллионы бесполезных файлов журналов, которые заполняли все иноды. Я прибег к «locate», собрал все файлы, «расположенные» d, в текстовый файл, а затем удалил их один за другим. Потребовалось время, но сделал работу!
источник
locate
обратно, когда у вас осталось место на диске.Немного более безопасная версия, чем использование xargs, также не рекурсивная:
ls -p | grep -v '/$' | grep '\.pdf$' | while read file; do rm "$file"; done
Фильтрация наших каталогов здесь немного ненужна, так как «rm» не удалит его в любом случае, и его можно удалить для простоты, но зачем запускать что-то, что обязательно вернет ошибку?
источник
ls
является распространенным антипаттерном, которого определенно следует избегать, и добавляет сюда ряд дополнительных ошибок. Этоgrep | grep
просто не очень элегантно.find
хорошими и хорошо задокументированы здесь и в других местах. См., Например, mywiki.wooledge.org, чтобы узнать больше об этой и смежных темах.Использование GNU parallel (
sudo apt install parallel
) очень простоОн запускает многопоточные команды, где «{}» - переданный аргумент.
Например
ls /tmp/myfiles* | parallel 'rm {}'
источник
ls
непосредственно другим командам является опасным антипаттерном, и тот факт, что расширение подстановочного знака вызовет тот же сбой при выполнении,ls
как и в оригинальнойrm
команде ,parallel
делает некоторых людей, которые предпочитают избегать сложности, неудобными - если вы посмотрите под капот, это довольно непрозрачно. См. Ветку списка рассылки по адресу lists.gnu.org/archive/html/bug-parallel/2015-05/msg00005.html между Стефаном (одним из серых бород Unix & Linux StackExchange ) и Оле Танге (автор Parallel).xargs -P
также паралеллизует, но делает это более простым и тупым способом с меньшим количеством движущихся частей, что делает его поведение намного легче предсказать и обдумать.Для удаления первых 100 файлов:
rm -rf 'ls | голова -100 '
источник
Опция ниже кажется простой для этой проблемы. Я получил эту информацию из другой ветки, но она мне помогла.
Просто запустите приведенную выше одну команду, и она выполнит задачу.
источник