find -exec + vs find | xargs: qual escolher?

30

Entendo que a opção -exec pode receber uma + para imitar o comportamento de xargs . Existe alguma situação em que você preferiria uma forma sobre a outra?

Eu pessoalmente tendem a preferir a primeira forma, mesmo que apenas para evitar o uso de um tubo. Eu acho que os desenvolvedores de find devem ter feito as otimizações apropriadas. Estou correto?

    
por rahmu 27.06.2012 / 12:45

4 respostas

20

Você pode querer encadear chamadas para encontrar (uma vez, quando você aprendeu, que é possível, o que pode ser hoje). Isto é claro, só é possível enquanto você ficar em busca. Depois de canalizar para xargs, está fora do escopo.

Exemplo pequeno, dois arquivos a.lst e b.lst:

cat a.lst
fuddel.sh
fiddel.sh

cat b.lst
fuddel.sh

Nenhum truque aqui - simplesmente o fato de que ambos contêm "fuddel", mas apenas um contém "fiddel".

Suponhamos que não sabíamos disso. Pesquisamos um arquivo que corresponde a duas condições:

find -exec grep -q fuddel {} ";" -exec grep -q fiddel {} ";" -ls
192097    4 -rw-r--r--   1 stefan   stefan         20 Jun 27 17:05 ./a.lst

Bem, você pode saber que a sintaxe do grep ou de outro programa passa ambas as strings como condição, mas esse não é o ponto. Todo programa que pode retornar true ou false, dado um arquivo como argumento, pode ser usado aqui - o grep era apenas um exemplo popular.

E note que você pode seguir encontrar -exec com outros comandos find, como -ls ou -delete ou algo similar. Note que excluir não só faz rm (remove arquivos), mas rmdir (remove diretórios) também.

Essa cadeia é lida como uma combinação E de comandos, desde que não seja especificado de outra forma (a saber, com uma opção -or (e parens (que precisam de mascaramento))).

Então você não está deixando a cadeia de encontrar, o que é uma coisa útil. Eu não vejo nenhuma vantagem em usar o -xargs, já que você tem que ter cuidado ao passar os arquivos, o que é algo que o find não precisa fazer - ele automaticamente manipula a passagem de cada arquivo como um único argumento para você.

Se você acredita que precisa de algum mascaramento para encontrar {} chaves , sinta-se livre para visitar minha pergunta que pede evidências. Minha afirmação é: você não faz.

    
por 27.06.2012 / 17:23
21

Nomes de arquivos de tubulação com segurança para xargs exigem que o find ofereça suporte à opção -print0 e o xargs tenha a opção correspondente para lê-la ( --null ou -0 ). Caso contrário, nomes de arquivos com caracteres não imprimíveis ou barras invertidas ou citações ou espaço em branco no nome podem causar um comportamento inesperado. Por outro lado, find -exec {} + está na POSIX find spec , por isso é portátil, e é tão seguro quanto find -print0 | xargs -0 , e definitivamente mais seguro que find | xargs . Eu recomendaria nunca fazendo find | xargs sem -print0 .

    
por 27.06.2012 / 14:58
10

Se você usar o formulário -exec ... ; (lembrando-se de escapar do ponto-e-vírgula), estará executando o comando uma vez por nome de arquivo. Se você usa -print0 | xargs -0 , você executa vários comandos por nome de arquivo. Você definitivamente deve usar o formulário -exec + , que coloca vários arquivos em uma única linha de comando e é muito mais rápido quando um grande número de arquivos está envolvido.

Uma grande vantagem de usar xargs é a capacidade de executar vários comandos em paralelo usando xargs -P . Em sistemas com vários núcleos, isso pode proporcionar enorme economia de tempo.

    
por 27.06.2012 / 12:55
6

Em relação ao desempenho, achei que -exec … + seria simplesmente melhor, porque é uma única ferramenta que faz todo o trabalho, mas uma parte da documentação do GNU findutil diz que -exec … + pode ser menos eficiente em alguns casos:

[find with -exec … +] can be less efficient than some uses of xargs; for example xargs allows new command lines to be built up while the previous command is still executing, and allows you to specify a number of commands to run in parallel. However, the find ... -exec ... + construct has the advantage of wide portability. GNU findutils did not support ‘-exec ... +’ until version 4.2.12 [January 2005]; one of the reasons for this is that it already had the ‘-print0’ action in any case.

Eu não sabia exatamente o que isso significava, então perguntei no bate-papo onde derobert o explicou:

find probably could continue to search for the next batch of files while the -exec … + is running, but it doesn't.
find … | xargs … does, because then the find is a different process, and it keeps running until the pipe buffer fills up

(formatação por mim)

Então tem isso. Mas se o desempenho realmente importa, você teria que fazer um benchmarking realístico ou até mesmo se perguntar se você mesmo gostaria de usar o shell para tais casos.

Aqui neste site, eu acho melhor aconselhar as pessoas a usar o -exec … + sempre que possível, porque é mais simples e pelas razões mencionadas nas outras respostas aqui (por exemplo, manipular nomes estranhos de arquivos sem ter que pensar muito).

    
por 06.11.2016 / 18:44