Eu entendo que -exec pode ter uma + opção para imitar o comportamento de xargs. Existe alguma situação em que você “preferiria uma forma em vez da outra?

Pessoalmente, tendo a preferir a primeira forma, mesmo que apenas para evitar o uso de um tubo. Acho que certamente os desenvolvedores de find deve” ter feito as otimizações apropriadas. Estou correto?

Resposta

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

Pequeno exemplo, 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”.

Suponha que não soubéssemos disso. Procuramos um arquivo que corresponda a 2 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, talvez você conheça a sintaxe do grep ou de outro programa para passar ambas as strings como condição, mas que ” Esse não é o ponto. Todo programa que pode retornar verdadeiro ou falso, dado um arquivo como argumento, pode ser usado aqui – grep foi apenas um exemplo popular.

E observe, você pode seguir find -exec com outros comandos de localização, como -ls ou -delete ou algo semelhante. Observe que a exclusão não apenas rm (remove arquivos), mas também rmdir (remove diretórios) também.

Tal cadeia é lida como uma combinação AND de comandos, desde que não seja especificado de outra forma (ou seja, com uma opção -or (e parênteses (que precisam ser mascarados))).

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

Se você acredita que precisa de algum mascaramento para encontrar {} colchetes , fique à vontade para visitar minha pergunta que pede evidências. Minha afirmação é: Você não.

Comentários

  • Esta postagem abriu meus olhos para uma nova maneira de usar find. Muito obrigado!
  • ” Não ‘ não vejo nenhuma vantagem em usar -xargs “. Qual ‘ é a -exec maneira de fazer xargs -P4 para que três dos quatro núcleos não ‘ fiquem inativos?
  • @DamianYerrick: Finalize o comando -exec não em “; ” mas com um + (/ sinal de mais).

Resposta

O encaminhamento seguro de nomes de arquivos para xargs requer que seu find suporte o -print0 opção e seu xargs tem a opção correspondente para lê-lo (--null ou -0). Caso contrário, nomes de arquivos com unprintab Os caracteres le ou barras invertidas ou aspas ou espaços em branco no nome podem causar um comportamento inesperado. Por outro lado, find -exec {} + está na POSIX find especificação , por isso é portátil e é quase tão seguro quanto find -print0 | xargs -0 e definitivamente mais seguro do que find | xargs. Eu recomendo nunca fazer find | xargs sem -print0.

Comentários

  • Uma exceção notável à portabilidade de find … -exec … {} + é o OpenBSD, que só adquiriu esse recurso com a versão 5.1 lançada em 2012. Todos os BSDs tiveram -print0 por vários anos, até mesmo o OpenBSD (embora tenha resistido a esse recurso por um tempo também). Solaris, por outro lado, mantém os recursos POSIX, então você obtém -exec + e nenhum -print0.
  • -print0 é chato e você pode argumentar xargs --delimiter "\n" isn ‘ t equivalente, eu ‘ nunca usei o primeiro depois de descobrir o último .
  • Não ‘ não vejo como -0 é mais chato do que --delimiter "\n".
  • Além de -0, GNU xargs precisa de -r para evitar a execução do comando se ‘ não houver entrada.
  • Outro problema de | xargs -r0 cmd é que cmd ‘ s stdin é afetado (dependendo da xargs implementação, ele ‘ s /dev/null ou o pipe.

Resposta

Se você usar a forma -exec ... ; (lembrando para escapar do ponto-e-vírgula), você está executando o comando uma vez por nome de arquivo. Se usar -print0 | xargs -0, você executará vários comandos por nome de arquivo. Você definitivamente deve usar o -exec + formulário, 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 uma grande economia de tempo.

Comentários

  • Você quis dizer -P em vez de -p. Lembre-se de que xargs -P não está no padrão POSIX, enquanto find -exec {} + está, o que é importante se você deseja portabilidade.
  • @Alexios Você não ‘ não precisa escapar do sinal de mais, porque ele não tem um significado especial para o shell: find /tmp/ -exec ls "{}" + funciona muito bem.
  • Corrente, é claro. Eu ‘ tenho escapado de tudo depois do -exec por tanto tempo (eu ‘ ma masoquista , Eu não ‘ nem mesmo uso aspas para escapar {}, sempre digito \{\}; não ‘ não pergunte), tudo parece que deve ser escapado agora.
  • @Alexios: Se você encontrar um exemplo (exceto por ser um masoquista) onde o mascarar as chaves é útil, forneça-o como uma resposta à minha pergunta aqui – afaik esta dica está desatualizada e é apenas um relíquia na página de manual. Eu ‘ nunca vi um exemplo em que find /tmp/ -exec ls {} + ‘ não funcionasse.
  • Para mim, esta é a memória muscular formada na época do SunOS 4. Como ‘ faço isso há anos, não percebi quando bash começou a aceitar as chaves literalmente. Eu ‘ tenho certeza de que pelo menos uma das conchas antigas que ‘ usei com encaixes sibilantes se as chaves não tivessem ‘ t escapou.

Resposta

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

[encontre com -exec … +] pode ser menos eficiente do que alguns usos de xargs; por exemplo, xargs permite que novas linhas de comando sejam construídas enquanto o comando anterior ainda está em execução e permite que você especifique um número de comandos a serem executados em paralelo. No entanto, a construção find ... -exec ... + tem a vantagem de ampla portabilidade. GNU findutils não suportava ‘-exec ... +’ até a versão 4.2.12 [janeiro de 2005] ; uma das razões para isso é que ele já tinha a ação ‘-print0’ em qualquer caso.

Não tinha certeza do que isso significava, então perguntei no bate-papo onde derobert explicou isso como:

find provavelmente poderia continuar a procurar o próximo lote de arquivos enquanto o -exec … + está em execução, mas não.
find … | xargs … está, porque então a localização é um processo diferente e mantém executando até que o buffer do pipe se encha

(Formatando por mim.)

Então é isso. Mas se o desempenho realmente importa, você teria que fazer um benchmarking realista ou melhor, até mesmo se perguntar se você gostaria de usar o shell para esses casos.

Aqui neste site eu acho que é melhor aconselhar as pessoas a use a forma -exec … + sempre que possível porque é mais simples e pelos motivos mencionados nas outras respostas aqui (por exemplo, lidar com nomes de arquivos estranhos sem ter que pensar muito).

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *