Почему 'find -delete' рекурсивно удаляет все файлы в каталоге


15

Так что следующее поведение unix find просто дорого стоит мне:

> 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 состоит из различных опций, которые объединяются в выражения выражений.

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 можно не указывать. В этом случае, не действие вообще, поэтому наиболее очевидные добавляются неявно: -print. (См. Второй абзац раздела «ВЫРАЖЕНИЯ», приведенного выше)


Думаю, я был просто идиотом, потому что сначала не читал руководство .. Но было просто добавить -deleteфлаг :-) Но есть ли причина, по которой кто-то когда-либо делал, find . -deleteа не rm -rf .? Или это просто способ findсинтаксического анализа и обработки своих аргументов?
mszep

1
О, я полностью согласен с тем, что синтаксис очень опасен - но этого трудно избежать, так как это всего лишь особый случай синтаксиса выражения командной строки find, который является чрезвычайно мощным. Мощный как в " Мощной бензопиле ".
Фолькер Сигел

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

Ах да, проблема в заголовке - я хотел проиллюстрировать использование печати вместо -delete, как -nвариант; Конечно, первая команда вообще не должна иметь практического применения; Я пойду поменяю это.
Фолькер Сигел

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.