TL; DR: найкращим способом є використання -exec rmзамість -delete.
find a \( -name b -prune \) -o -type f -exec rm {} +
Пояснення:
Чому знайти скаржаться , коли ви намагаєтеся використовувати -deleteз -prune?
Коротка відповідь: тому що це -deleteозначає -depthі -depthробить -pruneнеефективним.
Перш ніж ми прийдемо до довгої відповіді, спочатку спостерігайте за поведінкою знахідки з і без -depth:
$ find foo/
foo/
foo/f1
foo/bar
foo/bar/b2
foo/bar/b1
foo/f2
Немає гарантій щодо замовлення в одному каталозі. Але є гарантія, що каталог буде оброблений перед його вмістом. Зверніть увагу foo/перед будь-яким foo/*і foo/barперед будь-яким foo/bar/*.
Це можна змінити за допомогою -depth.
$ find foo/ -depth
foo/f2
foo/bar/b2
foo/bar/b1
foo/bar
foo/f1
foo/
Зверніть увагу, що зараз всі foo/*з'являються раніше foo/. Те саме з foo/bar.
Більш довга відповідь:
-pruneзапобігає спуску в каталог. Іншими словами -pruneпропускає вміст каталогу. У вашому випадку -name b -pruneне дозволяє знайти спуск у будь-який каталог з назвою b.
-depthзмушує обробляти вміст каталогу перед самим каталогом. Це означає, що до моменту, коли знахідка обробляє запис каталогу, bйого вміст уже оброблений. Таким чином, -pruneце неефективно з -depthдією.
-deleteМається на увазі, -depthщоб він міг видалити файли спочатку, а потім порожній каталог. -deleteвідмовляється видаляти непорожні каталоги. Я здогадуюсь, можна було б додати опцію, щоб примусити -deleteвидаляти непорожні каталоги та / або запобігти -deleteнатяк -depth. Але це вже інша історія.
Є ще один спосіб досягти того, що ви хочете:
find a -not -path "*/b*" -type f -delete
Це може бути, а може і не простіше запам'ятати.
Ця команда все ще спускається до каталогу bта обробляє кожен файл у ній лише для того, -notщоб їх відхилити. Це може бути проблемою з продуктивністю, якщо каталог bвеличезний.
-pathпрацює інакше, ніж -name. -nameзбігається лише з ім'ям (файлу чи каталогу), тоді -pathяк відповідає всім шляхом. Наприклад, спостерігайте за стежкою /home/lesmana/foo/bar. -name -barвідповідатиме тому, що ім’я є bar. -path "*/foo*"відповідатиме тому, що рядок /fooстоїть на шляху. -pathмає деякі тонкощі, які слід розібратися, перш ніж використовувати його. Прочитайте сторінку людини findдля отримання більш детальної інформації.
Слідкуйте за тим, щоб це не на 100% надійне. Є шанси на "помилкові позитиви". Як команда написана вище, вона пропустить будь-який файл, у якому є будь-яка батьківська директорія, з імені якої починається b(позитивно). Але він також пропустить будь-який файл, ім'я якого починається з bнезалежно від позиції в дереві (хибнопозитивний). Це можна виправити, написавши кращий вираз, ніж "*/b*". Це залишається як вправа для читача.
Я припускаю, що ви використовували aі bяк заповнювачі, і справжні імена, як allosaurusі brachiosaurus. Якщо поставити brachiosaurusна місце, bто кількість помилкових позитивних результатів буде різко зменшена.
По крайней мере, помилкові спрацьовування будуть НЕ видалені, так що це буде не так трагічно. Крім того, ви можете перевірити помилкові позитиви, спершу запустивши команду без -delete(але пам'ятайте, що розміщується мається на увазі -depth) та вивчити вихід.
find a -not -path "*/b*" -type f -depth
aкрімa/b?