Чому з -delete видалив файли в моєму / зберегти / директорії, коли find без видалення не зміг їх знайти?


20

Я хочу видалити всі файли з поточного дерева каталогів, крім тих, що в save. Я запустив цю команду:

 find . \( -name save -prune \) -o -type f -ls | grep /save/

і вона не знайшла жодної. Але коли я запустив цю команду:

 find . \( -name save -prune \) -o -type f -delete

Усі ці файли в / зберегти / пішли. Що я пропускаю?


4
Ой ... Я сьогодні щось дізнався (дякую тобі). І я рекомендую просту mv save/ ../some/safer/locationдо такої "загальної" команди видалення (... але, звичайно, перед вашою публікацією я би зробив ту саму перевірку і зіткнувся з тією ж проблемою!). Тепер ідіть, знайдіть хорошого "видалення" для файлової системи файли були на ^^
Олів'є Дулак

3
Мій біль - це ваша профілактика.
Отей

1
1000 завдяки вам. Код (найчастіше?) Працює таємничими способами ...
Олів'є Дулак


@lesmana Я підтримав вашу відповідь там. на жаль, моя версія знахідки не дає мені такого приємного попередження :(
Отей

Відповіді:


26

-deleteозначає, -depthщо не працює -prune( -depthпочинається з листя). У цьому посібнику щодо версії GNU -deleteє попередження ( це розширення FreeBSD, яке також підтримується GNU findта кількома іншими реалізаціями).

info find --index-search=-delete

Використання дії '-delete' в командному рядку автоматично включається опцію '-depth' (* зверніть увагу на вирази: :). Це може бути дивно, якщо ви раніше лише тестували "-print", тому, як правило, найкраще пам'ятати, щоб явно використовувати "-depth".

info find --index-search=-prune

Оскільки "-delete" означає "-depth", використання "-prune" у поєднанні з "-delete" може призвести до видалення більше файлів, ніж ви планували.

Тут у вас є можливість використовувати rmзамість цього:

find . -name save -prune -o -type f -exec rm -f {} +

(Потенційно небезпечними , якщо є каталог записується іншими там, як можна було б зробити вам видалити файли за межами поточного дерева каталогів, замінивши каталоги з симлінк під час запуску цієї команди).

Більш безпечна альтернатива:

find . -name save -prune -o -type f -execdir rm -f -- {} \;

У цьому немає зазначеної вище проблеми, але це означає запуск одного rmфайлу. --Необхідно для реалізації FreeBSD, а НЕ GNU один , що імена файлів префікси з ./.

Як варіант, як пропонує Костас:

LC_ALL=C find . ! -name save ! -path '*/save/*' -type f -delete

(але це все-таки непотрібно спускається в saveкаталоги)

Це LC_ALL=Cтак *відповідає будь-якій послідовності байтів (навіть тим, які не утворюють дійсних символів у поточному мові). Зауважте, що це вплине на мову повідомлень про помилки (англійська замість мови користувача).


З чим тут питання безпеки rm?
jrw32982 підтримує Моніку

@ jrw32982, див. редагувати із посиланням на посібник з GNU
Stéphane Chazelas
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.