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-deleteПрапор 's працює так, як rmdirпри видаленні каталогів. Якщо каталог не порожній, коли його досягнуто, його не можна видалити.

Спершу вам потрібно спорожнити каталог. Оскільки ви вказуєте -type d, findце не зробить для вас.

Ви можете вирішити це, зробивши два проходи: спочатку видаліть усе з названих dirs __pycache__, а потім видаліть всі dirs з назвою __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 (1) говорить , що для -delete«... Глибини першої обробки обходу мається на увазі цим варіантом.», І GNU знахідка (1) говорить: «... -Видалити увазі -depth , ...», так що це не повинен необхідно додати -depthдо команди.
G-Man каже: "Відновіть Моніку"

1
З сторінки GNU find: "Щоб запобігти плутанині, глобальні параметри слід вказати в командному рядку після списку початкових точок, безпосередньо перед першим тестом, позиційним варіантом або дією. Якщо ви вкажете глобальний варіант в іншому місці, знайдіть буде надіслати попередження, пояснивши, що це може заплутати. " Тепер, -deleteце "глобальний варіант" після ~команди, заданої. Я також помітив, що немає значення, додаєте ви -depthчи ні. Непорожні каталоги залишаються незавершеними (але це, мабуть, тому, що я -maxdepthтеж використовую )
Девід Тонхофер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.