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

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

find . -type d -exec rmdir {} 2>/dev/null \;

, но мне нужно запускать несколько раз, чтобы удалить каталоги, содержащие только пустые каталоги. Более того, это довольно медленно, особенно под cygwin.

118 голосов | спросил maaartinus 2 MaramWed, 02 Mar 2011 00:48:13 +03002011-03-02T00:48:13+03:0012 2011, 00:48:13

5 ответов


159

Объединяя опции и предикаты GNU find, эта команда должна выполнить задание:

find . -type d -empty -delete
  • -type d ограничивает каталоги
  • -empty ограничивает пустые
  • -delete удаляет каждую директорию

Дерево идет от листьев без необходимости указывать -depth, как это подразумевается в -delete.

ответил Christophe Drevet-Droguet 2 Jpm1000000pmThu, 02 Jan 2014 18:34:21 +040014 2014, 18:34:21
49

Список каталогов, глубоко вложенных в первую очередь.

find . -depth -type d -exec rmdir {} \; 2>/dev/null

(Обратите внимание, что перенаправление применяется к команде find в целом, а не только к rmdir. Перенаправление только для rmdir приведет к значительное замедление, так как вам нужно вызвать промежуточную оболочку.)

Вы можете избежать запуска rmdir в непустых каталогах, передав предикат -empty, чтобы найти. GNU находит тесты в каталоге, когда он собирается запустить команду, поэтому будут удалены каталоги, которые только что были опустели.

find . -depth -type d -empty -exec rmdir {} \;

Еще один способ ускорить - группировать вызовы rmdir. Оба они, вероятно, будут заметно быстрее оригинала, особенно в Cygwin. Я не ожидаю большой разницы между этими двумя.

find . -depth -type d -print0 | xargs -0 rmdir 2>/dev/null
find . -depth -type d -exec rmdir {} + 2>/dev/null

Какой метод быстрее, зависит от того, сколько у вас непустых каталогов. Вы не можете комбинировать -empty с методами группировки вызовов, потому что тогда каталоги, содержащие только пустые каталоги, не будут пустым к моменту поиска find. р>

Другим методом будет выполнение нескольких проходов. Является ли это быстрее, зависит от многих вещей, в том числе, может ли целая иерархия каталогов оставаться в дисковой кеше между find работает.

while [ -n "$(find . -depth -type d -empty -print -exec rmdir {} +)" ]; do :; done

В качестве альтернативы используйте zsh. классификатор glob F соответствует непустым каталогам, поэтому /^F соответствует пустым каталогам. Каталоги, содержащие только пустые каталоги, не могут быть легко сопоставлены.

while rmdir **/*(/N^F); do :; done

(Это завершается, когда rmdir получает пустую командную строку.)

ответил Gilles 2 MaramWed, 02 Mar 2011 01:08:38 +03002011-03-02T01:08:38+03:0001 2011, 01:08:38
5

Если вы просто применили -p к вашему rmdir, который будет работать за один проход. Это не будет красивым или оптимальным, но он должен получить все. Это сообщает rmdir об удалении любых непустых родительских каталогов того, который вы удаляете.

Вы можете немного сэкономить, добавив тест -empty для поиска, поэтому он не беспокоит непустые каталоги.

ответил mattdm 2 MaramWed, 02 Mar 2011 01:06:17 +03002011-03-02T01:06:17+03:0001 2011, 01:06:17
1

find . -depth -type d -exec rmdir {} +

- самый простой и стандартный ответ на этот вопрос.

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

ответил schily 6 52015vEurope/Moscow11bEurope/MoscowFri, 06 Nov 2015 15:48:31 +0300 2015, 15:48:31
0
Команда

rm -r */ легко работала для меня. rm должен требовать -f принудительно удалять каталоги с файлами. rm -r должен удалять только пустые каталоги. Я открыт для того, почему это может быть неправильно. Это также должно оставить файлы, так как */ просматривает только папки.

ответил libroman2 22 J0000006Europe/Moscow 2018, 17:36:06

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132