find: “-exec rm {} \;” vs. “-delete” - por que o primeiro é amplamente recomendado?

2

Por que é que os artigos em find sempre usam -exec rm {} \; nos casos em que o mais curto e mais fácil de digitar e ler -delete parece, até onde eu sei, funcionar tão bem?

Eu percebo que há casos em que rm com algumas opções como -r -f , por exemplo, pode fazer mais alguns truques, mas há muitos exemplos de -exec rm {} \; em tutoriais em todo o net mas virtualmente nenhum exemplo do uso de -delete .

O que estou perdendo? Existe alguma razão para isso?

    
por Lew Rockwell Fan 23.06.2017 / 20:41

3 respostas

5

tl; dr: -delete não é requerido pelo POSIX, -exec é.

Fatos

Página man do POSIX 1003.1 para find especifica -exec mas não -delete .

Isso significa que -exec deve funcionar virtualmente em todos os lugares. Eu ficaria surpreso ao encontrar find que tem -delete sem -exec . O oposto é bem possível. Especialmente sistemas leves que usam busybox tendem a fornecer apenas opções básicas de linha de comando.

Por exemplo Eu tenho um OpenWRT em um dos meus roteadores e seu find entende -exec , ele não entende -delete .

Não ter -delete não é grande coisa quando você tem -exec rm … . Por outro lado, -delete não pode substituir -exec em geral. É um design inteligente permitir omitir -delete primeiro.

Experiência pessoal, observações e opiniões

O acima deve ser o principal motivo pelo qual -exec rm {} \; é tão amplamente recomendado. O secundário pode ser um efeito de bola de neve. Os usuários lêem artigos e exemplos, se familiarizam com -exec e publicam seus próprios comandos (por exemplo, aqui no Superusuário). Alguns deles podem nem saber que -delete existe.

Algumas vezes vi (ou dei) comentários como 'Você pode usar -delete . E as respostas foram como "Obrigado, eu não sabia disso". Não me lembro de nenhuma resposta "Eu sei, mas isso não é POSIX '.

Tendo dito tudo isso, eu costumo mencionar -delete sempre que -exec rm {} \; aparece. O motivo é -delete não gerar um novo processo, enquanto -exec rm {} \; invoca o rm separado para cada arquivo correspondente. Se você não puder usar -delete , seu próximo pensamento deverá ser -exec rm {} + , que pode remover vários arquivos com cada rm .

Por que razão não é -exec … + amplamente recomendado? Pode ser por causa de suas limitações. Eu posso imaginar um usuário inexperiente pensando "Isso funciona com rm , deixe-me usá-lo com mv ! ' Então -exec mv {} foo/ + não funciona porque {} precisa estar no final, logo antes de + . O usuário fica frustrado e volta para o mama Windows.

Recomendar -delete costuma ser seguro aqui no Superusuário, eu acho. A maioria das perguntas especificam comandos "grandes" de OS-es, find que são ricos em opções. E mesmo que haja um usuário cujo find seja limitado, provavelmente receberei feedback. Ele ou ela diz que a solução não funciona para eles e sugiro -exec rm … , explique o problema, etc.

Um artigo independente que recomenda -delete não receberá esse feedback. Em caso de problemas, o usuário simplesmente acessará o próximo link retornado pelo Google.

    
por 24.06.2017 / 01:34
3

A diferença está na flexibilidade. Se você usar -exec, execute um comando para cada arquivo selecionado. Se você usar -exec, terá flexibilidade para aplicar outras opções de busca. Com -delete você está restrito ao uso de -prune. Além disso, o posicionamento de -delete afeta seus resultados. Veja o snippet de documentação abaixo:

-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 every-
    thing  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.

-exec command ;
    Execute  command;  true  if 0 status is returned.  All following arguments 
    to find are taken to be arguments to the command until an argument
    consisting of ‘;’ is encountered.  The string ‘{}’ is replaced by the 
    current file name being processed everywhere it occurs in the arguments
    to  the  command, not just in arguments where it is alone, as in 
    some versions of find.  Both of these constructions might need to be escaped
    (with a ‘\’) or quoted to protect them from expansion by the shell.  
    See the EXAMPLES section for examples of the use of  the  -exec  option.
    The specified command is run once for each matched file.  The 
    command is executed in the starting directory.   There are unavoidable security
    problems surrounding use of the -exec action; you should use the -execdir 
    option instead.

-exec command {} +
    This variant of the -exec action runs the specified command on the 
    selected files, but the command line is built by appending  each  selected
    file name at the end; the total number of invocations of the command 
    will be much less than the number of matched files.  The command line is
    built in much the same way that xargs builds its command lines.  
    Only one instance of ‘{}’ is allowed within the  command.   The  command  is
    executed in the starting directory
    
por 23.06.2017 / 21:02
0

A forma mais antiga "amplamente recomendada", ainda preferida em sistemas sem -delete , é (substituindo as elipses conforme apropriado):

find ... -print0 ... | xargs -0 /bin/rm ...

Isso limita os processos a dois em vez de permitir que -exec gerem potencialmente milhares, enquanto manipulam nomes de arquivos com caracteres especiais corretamente (enquanto que usar -print0 e omitir -0 de xargs permitiria que nomes de arquivos fossem divididos erroneamente).

Ele usa mais um processo que find com -delete e possui alguma sobrecarga de comunicação entre processos, mas é, como ocorre com -delete muito mais rápido que find ... -exec /bin/rm '{}' \' em quase todos os casos. / p>     

por 14.06.2018 / 02:16

Tags