Чому "find -delete" видаляє всі файли в каталозі рекурсивно


15

Тож наступна поведінка Unix знаходить мене дорого:

> touch foo
> touch bar
> ls  
bar  foo
> find . -name '*oo' -delete
> ls
bar
> touch baz
> ls
bar  baz
> find . -delete -name '*ar'
> ls
> #WHAAAT?

Як це має сенс?


2
Це питання пов'язане, може бути цікавим для майбутніх читачів. unix.stackexchange.com/questions/101282/…
Бернхард

Відповіді:


14

Командний рядок пошуку складається з різних типів параметрів, які поєднуються для формування виразів.

findВаріант -deleteцю дію.
Це означає, що він виконується для кожного відповідного файлу на даний момент.
Як перший варіант після контурів, всі файли відповідають ... ой!

Це небезпечно - але на сторінці людини принаймні є велике попередження :

Від man find:

ACTIONS
    -delete
           Delete  files; true if removal succeeded.  If the removal failed, an
           error message is issued.  If -delete fails, find's exit status  will
           be nonzero (when it eventually exits).  Use of -delete automatically
           turns on the -depth option.

           Warnings: Don't forget that the find command line is evaluated as an
           expression,  so  putting  -delete first will make find try to delete
           everything below the starting points you specified.  When testing  a
           find  command  line  that  you later intend to use with -delete, you
           should explicitly specify -depth in order to avoid later  surprises.
           Because  -delete  implies -depth, you cannot usefully use -prune and
           -delete together.


З подальшого опису в man find:

EXPRESSIONS
    The expression is made up of options (which affect overall operation rather
    than  the  processing  of  a  specific file, and always return true), tests
    (which return a true or false value), and actions (which have side  effects
    and  return  a  true  or false value), all separated by operators.  -and is
    assumed where the operator is omitted.

    If the expression contains no actions other than  -prune,  -print  is  per‐
    formed on all files for which the expression is true.


Перевірте, що findбуде робити команда:

Щоб побачити, що таке команда

find . -name '*ar' -delete

буде видалено, ви можете спочатку замінити дію -deleteна більш нешкідливу дію - наприклад, -flsабо -print:

find . -name '*ar' -print

Це дозволить надрукувати, на які файли впливає дія.
У цьому прикладі -принт можна залишити. В цьому випадку, не дія взагалі, тому найбільш очевидні додаються неявно: -print. (Дивіться другий абзац розділу "ВРАЗИ", цитований вище)


Я здогадуюсь, що я був просто ідіотцем, що спочатку не прочитав посібник. Але це було просто зрозуміло просто додати -deleteпрапор :-) Але чи є хтось причина, ніж хтось коли-небудь робити, find . -deleteа не rm -rf .? Або це просто трапляється способом findрозбору та обробки аргументів?
mszep

1
О, я повністю погоджуюся, що синтаксис дуже небезпечний - але цього важко уникнути, оскільки це лише особливий випадок синтаксису знаходження виразного рядка comman, який надзвичайно потужний. Потужний, як у " Потужній бензопилі ".
Volker Siegel

чи не вказана сторінка керівництва, warning: use -depth when testing stuff you later want to -deleteяку ви цитуєте, не говорить про те, що ви не зробили на своєму практичному прикладі?
pqnet

О, правильно - проблема в заголовку - я мав намір проілюструвати використання друку замість -delete, як -nваріант; Перша команда, звичайно, взагалі не повинна мати практичного використання; Я піду поміняти.
Volker Siegel

9

У findпорядку аргументів має значення багато.

Аргументами можуть бути варіанти, тести та дії. Зазвичай слід спочатку використовувати параметри, потім тести, а потім дії.

Іноді findнавіть попереджає про можливе неправильне замовлення (наприклад, коли ви використовуєте -maxdepthпісля інших аргументів), але іншим, здається, це не так.

Що find . -delete -name '*ar'таке:

  1. Знаходить файли та каталоги в поточному каталозі.
  2. Видаляє їх ВСІ, як вони знайдені!
  3. Потім бачить, чи вони названі як "* ar" (ця частина зараз не має ефекту).

Можливо, ви хочете зробити це:

find -name '*ar' -delete

Це визначатиме, чи відповідає він кожному файлу, '*ar'і лише якщо він задовольняє умові, він видалить файл.

Вибачте, якщо ви дізналися занадто пізно.

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