find -delete не удаляет непустые каталоги

32

Команда

$ find ~ -name .DS_Store -ls -delete

работает на Mac OS X, но

$ find ~ -name __pycache__ -type d -ls -delete

нет - каталоги найдены, но не удалены.

Зачем?

PS. Я знаю, что могу сделать

$ find ~ -name __pycache__ -type d -ls -exec rm -rv {} +

вопрос в том , почему find -delete это не работает.

ДСН
источник

Ответы:

36

find«S -deleteфлаг работает аналогично rmdirпри удалении каталогов. Если каталог не пустой, когда он достигнут, он не может быть удален.

Вы должны очистить каталог в первую очередь. Поскольку вы указываете -type d, findне будет делать это для вас.

Вы можете решить эту проблему, выполнив два прохода: сначала удалите все в именованных каталогах __pycache__, затем удалите все именованные каталоги __pycache__:

find ~ -path '*/__pycache__/*' -delete
find ~ -type d -name '__pycache__' -empty -delete

Несколько менее строго контролируется, но в одной строке:

find ~ -path '*/__pycache__*' -delete

Это удалит все, что есть в вашем доме, __pycache__как часть его пути.

ВНП
источник
При поиске 4.4.2 эта последняя команда должна быть find ~ -path '*/__pycache__*' -deleteили, вероятно, find ~ -path '*/__pycache__/*' -o -name __pycache__ -deleteбыть безопасной.
naught101
3
@ naught101, это должно быть find ~ \( -path '*/__pycache__/*' -o -name __pycache__ \) -deleteкак и имеет приоритет над или .
Стефан Шазелас
6

Есть несколько возможных причин для этого.

1) Вы сказали, что нужно удалять только каталоги ( -type d), и в этих каталогах по-прежнему есть файлы.

2) Ваши каталоги содержат только другие каталоги, поэтому -type dони позаботятся о проблеме содержимого. Однако вы используете OS-X, который в значительной степени основан на FreeBSD, и FreeBSD findпо умолчанию будет обрабатывать каталог до его содержимого.
Однако -depthсуществует возможность решить эту проблему, указав findобработать каталог после его содержимого.

find ~ -name __pycache__ -type d -ls -delete -depth

Эта проблема не существует в Linux, потому что -deleteопция неявно включает -depth.

 

FreeBSD man 1 find:

 -depth  Always true; same as the non-portable -d option. Cause find to
   perform a depth-first traversal, i.e., directories are visited in
   post-order and all entries in a directory will be acted on before
   the directory itself. By default, find visits directories in
   pre-order, i.e., before their contents. Note, the default is not
   a breadth-first traversal.

GNU man 1 find:

 -depth Process each directory's contents before the directory itself. The -delete
        action also implies -depth.
Патрик
источник
2
Да, но FreeBSD find (1) говорит -delete: «… эта опция подразумевает обработку в глубину в первую очередь», а GNU find (1) говорит: «… -delete подразумевает -depth ,…», поэтому не должен необходимо добавить -depthв команду.
G-Man говорит: «Восстановите Монику»
1
Из findсправочной страницы GNU : «Чтобы избежать путаницы, глобальные параметры следует указывать в командной строке после списка начальных точек, непосредственно перед первым тестом, позиционным параметром или действием. Если вы задаете глобальный параметр в каком-то другом месте, команда find найдет выдайте предупреждающее сообщение, объясняющее, что это может сбить с толку. " Теперь, -deleteэто «глобальная опция» после ~данной команды. Я также заметил, что не имеет значения, добавляете вы -depthили нет. Непустые каталоги остаются невостребованными (но это, вероятно, потому что я -maxdepthтоже использую )
Дэвид Тонхофер