Por que 'find -delete' exclui todos os arquivos em um diretório recursivamente

13

Portanto, o seguinte comportamento do unix find me custou caro:

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

Como isso faz sentido?

    
por mszep 17.08.2014 / 12:47

2 respostas

12

A linha de comando do find é feita a partir de diferentes tipos de opções, que são combinadas para formar expressões.

A find option -delete é uma ação.
Isso significa que ele é executado para cada arquivo correspondido até agora.
Como primeira opção após os caminhos, todos os arquivos são correspondidos ... oops!

É perigoso - mas a página do manual tem pelo menos um grande aviso :

De 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.


De mais acima em 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.


Ao experimentar o que um comando find fará:

Para ver o que um comando como

find . -name '*ar' -delete

excluirá, você pode substituir a ação -delete por uma ação mais inofensiva, como -fls ou -print :

find . -name '*ar' -print

Isso imprimirá quais arquivos são afetados pela ação.
Neste exemplo, a impressão pode ser deixada de fora. Nesse caso, não há ação, portanto, o mais óbvio é adicionado implicitamente: -print . (Veja o segundo parágrafo da seção "EXPRESSÕES" citada acima)

    
por 17.08.2014 / 13:14
9

Na ordem dos argumentos find , muito.

Argumentos podem ser opções, testes e ações. Normalmente, você deve usar as opções primeiro, depois os testes e, em seguida, as ações.

Às vezes, find até avisa sobre uma possível ordenação incorreta (por exemplo, quando você usa -maxdepth após outros argumentos), mas outras parecem que não.

O que o find . -delete -name '*ar' faz é:

  1. Localiza arquivos e diretórios no diretório atual.
  2. Exclui todos eles conforme são encontrados!
  3. Em seguida, ele vê se eles são nomeados como '* ar' (essa parte não tem efeito agora).

O que você provavelmente quer fazer é:

find -name '*ar' -delete

Isto irá, para cada ficheiro, ver se corresponde a '*ar' , e apenas se satisfizer a condição, irá apagar o ficheiro.

Desculpe se você descobriu tarde demais.

    
por 17.08.2014 / 13:10

Tags