Видаліть файли та каталоги за їх назвами. Немає такого файлу чи каталогу


32

Мені потрібно видалити всі зібрані дані:

  • названі каталоги build,
  • названі каталоги obj,
  • * .so файли.

Я написав команду

find \( -name build -o -name obj -o -name *.so \) -exec rm -rf {} \;

який проходить через всі каталоги рекурсивно і видаляє все, що мені потрібно.

Чому я маю такий результат у кінці? Можливо, я повинен написати іншу команду.

find: `./3/obj': No such file or directory
find: `./3/build': No such file or directory
find: `./1/obj': No such file or directory
find: `./1/build': No such file or directory
find: `./2/obj': No such file or directory
find: `./2/build': No such file or directory

за якою системою ви знаходитесь? Ви завжди повинні користуватися findтаким чином, find /search_directory optionsопускаючи пошуковий каталог - це не дуже гарна ідея
Kiwy

Автоматичне видалення, як це, погана ідея. У вас може бути сценарій, який дасть вам кандидатів, на які ви потім повинні ознайомитись, щоб переконатися, що ви не видаляєте нічого важливого чи необхідного в систему. Ви не є явним, де ви це запустите. Якщо ви робите це лише в користувальницькому просторі, я вважаю, що це не може принести великої шкоди, але ви повинні переконатися, що ви не робите цього в системній області випадково. Ви точно хочете запустити такий сценарій як користувач.
Faheem Mitha

@ Kiwy, @ FaheemMitha, команда буде використовуватися лише в дирекції проекту; це не принесе ніякої шкоди.
Максим Дмитрієв

Відповіді:


54

Використовуйте -pruneв каталогах, які ви все одно збираєтеся видалити, щоб сказати findне турбуватися, намагаючись знайти в них файли:

find . \( -name build -o -name obj -o -name '*.so' \) -prune -exec rm -rf {} +

Також зауважте, що *.soпотрібно цитувати, оскільки в іншому випадку вона може бути розширена оболонкою до списку .soфайлів у поточному каталозі.

Еквівалент вашого -regexтипу GNU був би:

find . \( -name build -o -name obj -o -name '*?.so' \) -prune -exec rm -rf {} +

Зауважте, що якщо ви збираєтесь використовувати синтаксис, визначений GNU, ви можете використовувати -deleteзамість цього -exec rm -rf {} +. З -delete, GNU findвключається -depthавтоматично. Він не запускає зовнішні команди, тому таким чином він є більш ефективним, а також безпечнішим, оскільки він видаляє стан гонки, коли хтось, можливо, зможе змусити вас видалити неправильні файли, змінивши каталог на символьне посилання між часом findзнаходить файл і rmвидаляє його (див. info -f find -n 'Security Considerations for find'подробиці).

find . -regextype posix-egrep -regex '.*/((obj|build)(/.*)?|.+\.so)' -delete

-deleteтакож краще обробляє такі речі, як пробіли
Ізката,

@Izkata, не кращий, ніж у -exec rm -rf {} +них теж немає проблем.
Стефан Шазелас

@StephaneChazelas - я збентежений {}- вони повинні бути цитованими чи ні? Здається, це працює без лапок, але в прикладі використовується посібник GNU Findutils'{}' . Не могли б ви уточнити?
grebneke

1
@grebneke, я думаю, що десь є публікація, в якій цитати претензій можуть знадобитися в дуже старих версіях csh, але я ніколи не міг перевірити цю заяву. Вони не потрібні в жодній сучасній оболонці, яку я знаю. POSIX їх точно не вимагає. У прикладах POSIX не використовують їх.
Стефан Шазелас

3
І -deleteне можна використовувати з каталогами.
St0rM

8

Я думаю, причина полягає в тому, що findспочатку видаляється дерево каталогів і намагається перевірити вміст каталогу, що, очевидно, не найкращий можливий порядок. Ви можете змусити findспочатку перевірити вміст:

find . -depth ...

Вам слід подумати про використання -deleteфайлів та -exec rmdirкаталогів.


0

Моє рішення.

find . -regextype posix-egrep -regex ".*/(obj|build|.+\.so)" -prune -exec rm -rf {} +

+ vs \; в команді -exec


Це не завжди буде спрацьовувати, лише якщо між видаленими каталогами не відбувається межі між виконанням.
Жил "ТАК - перестань бути злим"

@Gilles, що означає "межа між стратами"?
Максим Дмитрієв

1
-exec … {} +виконує команду для декількох файлів одночасно, стільки, скільки вміщається в командному рядку. Якщо файлів занадто багато (а точніше, якщо загальна довжина шляхів занадто довга), findбуде виконано кілька екземплярів rmі, таким чином, може в результаті видалити каталог, який він проходить. Це просто рідше, +ніж з ;, але +це не вирішує проблему.
Жил "ТАК - перестань бути злим"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.