xargs -I diferença da opção replace-str

16

Pelo meu entendimento, o seguinte deve significar exatamente o mesmo:

ls -1 | xargs file {}
ls -1 | xargs -I{} file {}

se a opção -I não for especificada, é o padrão para -I {}.

Quero listar todos os arquivos no diretório atual e executar o filecomando em cada um deles. Alguns têm espaços em seus nomes. No entanto, notei a diferença. Ver abaixo:

$ ls -1
Hello World
$ ls -1 | xargs file {}
{}:    ERROR: cannot open `{}' (No such file or directory)
Hello: ERROR: cannot open `Hello' (No such file or directory)
World: ERROR: cannot open `World' (No such file or directory)
$ ls -1 | xargs -I{} file {}
Hello World: directory

Com -I {} especificado explicitamente, os espaços em branco nos nomes dos arquivos são tratados conforme o esperado.

foresightyj
fonte
3
"se a opção -I não for especificada, é o padrão para -I {}" - isso está incorreto, pelo menos no GNU xargs.
Jjlin # 7/13
Eu entendo meu erro. Eu deveria especificar xargs fileou xargs -I{} file {}. Não deveria ser xargs file {}. Eu acho que ao especificar explicitamente -I {}, o bash o tratará como file "Hello World". Sem -I {}, é tratado como file Hello World.
foresightyj
1
(1) Essa discussão tem pouco a ver com o shell (bash). (2) É bom que você conheça a -1opção ls, mas ela está ativada por padrão quando a saída de lsé um arquivo ou um canal, para que você não precise dela aqui. (3) Você está confuso -Icom a opção preterida -i(minúscula I). -ifooé equivalente a -Ifoo, mas simples -ié equivalente a -I{}. Mas use -I{}. (4) Se você realmente quer fazer o que diz que quer, por que não dizer file *?
8283 Scott
@Scott Minha intenção original era escrever `find. -name "* .mov" | xargs -I {} arquivo {} `para encontrar todos os arquivos mov recursivamente e executá file-los. Mas vim com um exemplo mais simples usando ls. Você está certo. Para isso, file *é o melhor.
foresightyj
1
encontrar tem -exec.
Cristian Ciupitu 22/10/2013

Respostas:

20

O -Irequer um espaço reservado definido. A -iopção assumirá {}é o espaço reservado. Foi aqui que encontrei alguma suposição de {} man xargspelo menos no Cygwin e no CentOS.

O xargs chamado sem nenhuma das opções não precisa do espaço reservado e apenas acrescenta o STDIN ao final dos argumentos.

Apenas adicione echoseus exemplos para ver o que o xargs está fazendo:

$ ls -1
Hello World/

Seu exemplo de engano usa {}:

$ ls -1 | xargs echo file {}
file {} Hello World/

então o filecmd vê argumentos {} Hello Worlde erros.

Se você deseja usar explicitamente {}em sua chamada xargs:

$ ls -1 | xargs -i echo file {}
file Hello World/

Ou sem espaço reservado:

$ ls -1 | xargs echo file
file Hello World/

xargs, como chamado acima, não precisa do {}. Ele anexa o STDIN ao final do comando sem um espaço reservado. O uso de {} geralmente significa que você deseja que o STDIN em algum lugar no meio do cmd seja executado, como em:

$ ls -1 | xargs -i mv {} /path/to/someplace/.
johnnyB
fonte
Isso é muito claro. Mesmo que sua resposta seja um pouco tarde, mas lê-la realmente reforça minha compreensão.
precisa