A diferença está em quais dados o programa de destino está aceitando.
Se você usar apenas um canal, ele recebe dados no STDIN (o fluxo de entrada padrão) como uma pilha bruta de dados que podem ser classificados por uma linha por vez. No entanto, alguns programas não aceitam seus comandos no padrão, eles esperam que seja explicitado nos argumentos do comando. Por exemplo touch
leva um nome de arquivo como um parâmetro na linha de comando da seguinte forma: touch file1.txt
.
Se você tem um programa que gera nomes de arquivos na saída padrão e quiser usá-los como argumentos para touch
, você tem que usar xargs
o que lê os dados de fluxo stdin e converte cada linha no espaço argumentos separados para o comando.
Essas duas coisas são equivalentes:
# touch file1.txt
# echo file1.txt | xargs touch
Não use a xargs
menos que saiba exatamente o que está fazendo e por que é necessário. Geralmente, existe uma maneira melhor de fazer o trabalho do que usar xargs
para forçar a conversão. O processo de conversão também está cheio de possíveis armadilhas, como escape e expansão de palavras, etc.
xargs
e$(...)
), xargs é muito mais seguro que a substituição de comando. E não me lembro de ter encontrado um nome de arquivo legítimo com uma nova linha. Os problemas de escape e expansão de palavras não são problemas com a substituição de comandos, e não xargs?xargs -0
), o que é útil em conjunto comfind -print0
.xargs
chamar o programa através do shell com espaço separado args, ou ele realmente construir a lista de argumentos internamente (por exemplo. Para uso comexecv
/execp
)?-d \n
, embora o BSD xargs (OSX et al) não pareça suportar essa opção.Expandir as respostas já fornecidas,
xargs
pode fazer uma coisa interessante que está se tornando cada vez mais importante no cenário de computação multicore e distribuída de hoje: pode paralelizar tarefas de processo.Por exemplo:
irá codificar * .wav => * .flac, usando três processos ao mesmo tempo (
-P 3
).fonte
-exec
parâmetro não processará trabalhos paralelos.-0
argumentoxargs
faz com que considere oNULL
caractere como o delimitador do item de entrada.find -print0
saída itens delimitados por NULL. Essa é uma prática recomendada para nomes de arquivos que podem conter espaços, aspas ou outros caracteres especiais.O xargs é particularmente útil quando você tem uma lista de caminhos de arquivo no stdin e deseja fazer algo com eles. Por exemplo:
Vamos examinar este passo a passo:
Em outras palavras, nossa entrada é uma lista de caminhos para os quais queremos fazer algo.
Para descobrir o que o xargs faz com esses caminhos, um bom truque é adicionar
echo
antes do seu comando, assim:O
-n 1
argumento fará com que os xargs transformem cada linha em um comando próprio. Osed -i "s/color/colour/g"
comando substituirá todas as ocorrências decolor
comcolour
pelo arquivo especificado.Observe que isso só funciona se você não tiver espaços em seus caminhos. Se fizer isso, você deve usar caminhos terminados nulos como entrada para xargs passando a
-0
sinalização. Um exemplo de uso seria:Que faz o mesmo que descrevemos acima, mas também funciona se um dos caminhos tiver um espaço nele.
Isso funciona com qualquer comando que produza nomes de arquivos como saída, como
find
oulocate
. No entanto, se você o usa em um repositório git com muitos arquivos, pode ser mais eficiente usá-lo emgit grep -l
vez degit ls-files
:O
git grep -l "color" "*.tex"
comando fornecerá uma lista de arquivos "* .tex" que contêm a frase "cor".fonte
Seu primeiro argumento ilustra bem a diferença.
\ls | grep Cases | less
permite navegar na lista de nomes de arquivos produzidos porls
egrep
. Não importa que sejam nomes de arquivos, são apenas alguns textos.\ls | grep Cases | xargs less
permite procurar os arquivos cujos nomes são produzidos pela primeira parte do comando.xargs
pega uma lista de nomes de arquivos como entrada e um comando em sua linha de comandos e executa o comando com os nomes de arquivos em sua linha de comandos.Ao considerar usar
xargs
, tenha em mente que espera entrada formatada de maneira estranha: espaço em branco-delimitado, com\
,'
e"
usado para citar (de uma maneira incomum, porque\
não é citações dentro especiais). Use apenasxargs
se os nomes dos seus arquivos não contiverem espaços em branco ou\'"
.fonte
xargs
tem a-0, --null
opção de contornar a questão dos espaços (é muito provável que eu tenha aprendido isso com você :), então suponho que você esteja se referindo a umaxarg
chamada sem opções , mas estou intrigado com sua referência às aspas. Você tem um link ou um exemplo a esse respeito? . .. (ps| xargs less
é um "truque" acessível +1 .. obrigado ..No seu exemplo, você não precisa usar
xargs
nada, poisfind
fará exatamente e com segurança o que deseja fazer.Exatamente o que você deseja usar
find
é:Neste exemplo,
-maxdepth 1
significa apenas pesquisar no diretório atual, não desça em nenhum subdiretório; por padrão, o find irá procurar em todos os subdiretórios (que geralmente é o que você deseja), a menos que você o restrinja com maxdepth. O{}
é o nome do arquivo que será substituído em seu lugar e+
é um dos dois marcadores de fim de comando, sendo o outro;
. A diferença entre eles é que isso;
significa executar o comando em cada arquivo, um de cada vez, enquanto que+
executar o comando em todos os arquivos de uma só vez. Observe, no entanto, que seu shell provavelmente tentará se interpretar;
; portanto, você precisará escapar dele com um\;
ou outro';'
. Sim,find
tem uma série de pequenos aborrecimentos como esse, mas seu poder mais do que compensa isso.Ambos
find
exargs
são difíceis de aprender em primeiro lugar. Para ajudá-lo a aprender,xargs
tente usar a opção-p
ou,--interactive
que mostra o comando que está prestes a executar e pergunta se você deseja executá-lo ou não.Da mesma forma que
find
você pode usar-ok
no lugar de-exec
para perguntar se você deseja ou não executar o comando.Porém, há momentos em
find
que não é possível fazer tudo o que você deseja e é aí quexargs
entra. O-exec
comando aceita apenas uma instância de{}
exibição; portanto, se você receber um erro,find -type f -exec cp {} {}.bak \;
poderá fazê-lo da seguinte maneira :find -type f -print0 | xargs -0 -l1 -IX cp X X.bak
Você pode aprender mais sobre comandos de execução no manual do GNU Findutils .
Mencionei também que
find
o que você quer com segurança faz porque, ao lidar com arquivos, encontrará espaços e outros caracteres que causarão problemas, axargs
menos que você use a opção-0
ou--null
junto com algo que gere itens de entrada finalizados por um caractere nulo. do espaço em branco.fonte
'
ou"
podem ser problemáticos, enquanto que lidarão comfind
esses casos sem problemas.xargs
(junto comfind
,sort
,du
,uniq
,perl
e alguns outros) aceita um parâmetro de linha de comando para dizer "STDIN tem uma lista de arquivos, separados por um byte NUL (0x00)". Isso facilita o manuseio de nomes de arquivos com espaços e outros personagens engraçados. Os nomes de arquivos não contêm NULs.fonte