Как рекурсивно удалить каталоги с подстановочными знаками?

52

Я работаю через SSH над WD My Book World Edition. По сути, я хотел бы начать с определенного уровня каталогов и рекурсивно удалить все соответствующие подкаталоги .Apple*. Как бы я пошел об этом?

Я пытался

rm -rf .Apple* а также rm -fR .Apple*

ни один из удаленных каталогов, соответствующих этому имени в подкаталогах.

codedog
источник

Ответы:

73

find очень полезно для выборочного выполнения действий над целым деревом.

find . -type f -name ".Apple*" -delete

Здесь -type fон удостоверяется, что это файл, а не каталог, и может быть не совсем тем, что вам нужно, поскольку он также пропускает символические ссылки, сокеты и другие вещи. Вы можете использовать ! -type d, что буквально означает не каталоги, но тогда вы также можете удалить символьные и блочные устройства. Я бы посоветовал взглянуть на -typeпредикат на странице руководства find.

Чтобы сделать это строго с подстановочным знаком, вам нужна расширенная поддержка оболочки. Bash v4 имеет globstarопцию , которая позволяет вам рекурсивно сопоставлять подкаталоги, используя **. zshа kshтакже поддерживать эту модель. Используя это, вы можете сделать rm -rf **/.Apple*. Это не стандарт POSIX и не очень переносимый, поэтому я бы не использовал его в скрипте, но для одноразового действия интерактивной оболочки это нормально.

Шон Дж. Гофф
источник
3
Я могу приступить find . -type d -name .Apple*к работе - в нем перечислены все папки. Тем не менее, это не удается, когда я добавляю -deleteв конце. Это просто возвращается с кратким описанием использования. Он работает на BusyBox v1.1.1. Это имеет значение?
кодирование
1
-deleteтоже не POSIX. **был введен zshв начале 90-х годов. Это теперь (в хронологическом порядке появления) также в ksh93, fish, bash и tcsh.
Стефан Шазелас
1
+1 дляrm -rf **/.Apple*
Андрей Бойко
1
@codedog, если -deleteне работает, используйте -exec rm -f {} +вместо этого.
Wildcard
1
Можете ли вы findбыть многословным, когда он удаляет? Я полагаю, что метод "globstar" сделает это, добавив -vпереключатель.
Демис
17

Я столкнулся с проблемами при использовании findс -deleteиз-за преднамеренного поведения find(то есть отказ от удаления, если путь начинается с ./, что они делают в моем случае), как указано на его странице руководства:

 -delete

Удалить найденные файлы и / или каталоги. Всегда возвращает истину. Это выполняется из текущего рабочего каталога, так как поиск повторяется вниз по дереву. Он не будет пытаться удалить имя файла с символом "/" в его имени пути относительно "." по соображениям безопасности.
Обработка прохождения в глубину подразумевается этой опцией.
Следующие символические ссылки несовместимы с этой опцией.

Вместо этого я смог просто сделать

find . -type d -name 'received_*_output' -exec rm -r {} +

В вашем случае кажется, что указание на глобус (звездочка, *) было решением, но я хотел бы предоставить свой ответ на случай, если у кого-то еще возникнет подобная проблема.

ПРИМЕЧАНИЕ. Ранее мой ответ заключался в следующем: @Wildcard указал на недостатки безопасности в комментариях.

find . -type d -name 'received_*_output' | xargs rm -r
похлопывание
источник
1
Нет веских причин для использования xargsздесь. -exec rm -r {} \;или, что лучше, -exec rm -r {} +будет делать то же самое без ошибок в именах специальных символов. См. Почему циклическая обработка вывода find является плохой практикой?
Wildcard
Это хорошо знать. IMO не стоит понижать голос, поскольку команда все еще выполняет свою работу, но оптимизация производительности приветствуется.
Пэт
1
Если бы это была просто оптимизация производительности, я бы с вами согласился, но это не так. Это дыра в безопасности. Вы неправильно обрабатываете файлы с пробелами в именах, а созданное злонамеренно имя файла приведет к потере данных. Также см. Последствия для безопасности, связанные с забыванием заключить переменную в оболочку bash / POSIX ; кое -что из этого применимо, и оно может, по крайней мере, дать вам представление о типе проблем, о которых я говорю.
Wildcard
Попробуйте mkdir -p $'blah\nDocuments\n/etc\n/home\n/received__output'в своем каталоге и затем повторите ту же команду, если не уверены, что существует вероятность потери данных. Или, поскольку речь идет о Mac OS mkdir -p $'blah\nDocuments\n/Users\n/Applications\n/received__output'. ( Предупреждение: вы БУДЕТЕ удалить все свои файлы, если сделаете это. Это моя точка зрения.)
Wildcard
0

Возможно, что в вашей команде rm / find нет ничего плохого, но пользователь, с которым вы вошли, на самом деле не имеет прав на удаление. Использование ls -lв список вещей , с их разрешения, и вы можете определить , кто вы с idи groupsкоманды (или должны быть доступны). Если вы «неправильный пользователь» для этого, вам нужно будет либо изменить права доступа / владельца файлов, либо переключиться на другого пользователя.

froztbyte
источник
0

Пытаться:

shopt -s dotglob           # using Bash
printf '%s\n' ./.Apple*    # test
#rm -rf ./.Apple*    
январь
источник
1
dotglobздесь бесполезно. Смотрите эту страницу для примера того, что делает dotglob.
амфетамина
-1

Простая команда:

rm `find ./ -name '.Apple*'` -rf

Удачи!

KimKha
источник
4
Это очень подвержено ошибкам, найти ключ -exec.
Антон Барковский