O xargs pega sua entrada padrão e a transforma em argumentos da linha de comando.
find . -name '*.c' | xargs grep 'stdlib.h'
é muito parecido com
grep 'stdlib.h' $(find . -name '*.c') # UNSAFE, DON'T USE
E fornecerá os mesmos resultados, desde que a lista de nomes de arquivos não seja muito longa para uma única linha de comando. (O Linux suporta megabytes de texto em uma única linha de comando; portanto, geralmente você não precisa de xargs.)
Mas ambos são péssimos, porque quebram se os nomes de arquivos contiverem espaços . Em vez disso, find -print0 | xargs -0
funciona, mas o mesmo acontece
find . -name '*.c' -exec grep 'stdlib.h' {} +
Isso nunca canaliza os nomes de arquivos em qualquer lugar: find
agrupa-os em uma grande linha de comando e executa grep
diretamente.
\;
em vez de +
executar grep separadamente para cada arquivo, o que é muito mais lento. Não faça isso. Mas +
é uma extensão do GNU, então você precisa xargs
fazer isso com eficiência se não puder assumir a localização do GNU.
Se você deixar de fora xargs
, find | grep
o padrão será comparado à lista de nomes de arquivos find
impressos.
Então, nesse ponto, é melhor que você faça find -name stdlib.h
. Obviamente, com -name '*.c' -name stdlib.h
, você não obterá nenhuma saída porque esses padrões não podem corresponder e o comportamento padrão da localização é AND as regras juntas.
Substitua less
em qualquer ponto do processo para ver qual saída qualquer parte do pipeline produz.
Outras leituras: http://mywiki.wooledge.org/BashFAQ tem ótimas coisas.