Esse siteapresenta ao xargs
comando uma -J
opção que permite passar a entrada padrão para uma posição desejada no argumento do comando:
find . -name '*.ext' -print0 | xargs -J % -0 rsync -aP % user@host:dir/
mas em umPágina de manual do GNU xargsesta opção não está presente.
Qual é a maneira de fazer isso, para comandos que aceitam isso?
Responder1
Não tenho certeza se isso era o que você esperava, mas no mundo BSD (como o macOS) -I
eles -J
diferem na forma como eles passam as múltiplas "linhas" para o comando. Exemplo:
$ ls
file1 file2 file3
$ find . -type f -print0 | xargs -I % rm %
rm file1
rm file2
rm file3
$ find . -type f -print0 | xargs -J % rm %
rm file1 file2 file3
Assim -I
, com xargs executará o comando para cada elemento passado a ele individualmente. Com -J
, xargs executará o comando uma vez e concatenará todos os elementos e os passará como argumentos todos juntos.
Alguns comandos, como rm
ou, mkdir
podem receber vários argumentos e agir sobre eles da mesma maneira, como se você passasse um único argumento e os executasse várias vezes. Mas alguns aplicativos podem mudar dependendo de como você passa os argumentos para eles. Por exemplo o tar
. Você pode criar um arquivo tar e adicionar arquivos a ele ou pode criar um arquivo tar adicionando todos os arquivos de uma só vez.
$ find . -iname "*.txt" -or -iname "*.pdf" -print0 | xargs -0 -J % tar cjvf documents.tar.bz2 %
Responder2
Se este for o -J
sinalizador para a versão BSD, xargs
não acredito que exista uma opção equivalente exata para GNU xargs
. -J
substitui uma única ocorrência dereplstr(por exemplo %
) com cada linha chegando através da entrada padrão. A versão GNU possui umsemelhanteopção, porém: -I
1 . No entanto, você pode usarreplstrvárias vezes com essa bandeira.
Para casos de uso em que não é importante haver uma ou várias invocações de comando, você poderá usar o GNU xargs -I
como um substituto imediato. Mas seu exemplo usa rsync
e tenho certeza que você não deseja múltiplas invocações disso.
Seu melhor curso de ação é considerar alternativas começando com find
e a ação -exec
ou -execdir
. Existem duas variações destes. Um é análogo ao GNU -I
e o outro ao BSD -J
. Dê uma olhada nesses exemplos...
# Note the escaping of ';'
$ find /tmp -name '*.txt' -exec echo {} \;
/tmp/a.txt
/tmp/b.txt
..
/tmp/z.txt
Agora compare isso com isso:
$ find /tmp -name '*.txt' -exec echo {} +
/tmp/a.txt /tmp/b.txt .. /tmp/z.txt
A única diferença entre os dois é qual "modificador" aparece no final, +
ou ;
.
1 Outra coisa confusa é que a versão BSD também possui -I
e é semelhante em função a ambos -J
e ao GNU -I
! Mas isso -I
é afetado por outros sinalizadores e provavelmente não é o que você está procurando.