Usando xargs com entrada de um arquivo

41

Digamos que eu tenho um arquivo com o seguinte

bob
john
sue

Ora, estes diretamente corrospond (neste caso) padrão de URL, como http://example.com/persons/bob.tar, john.tar, sue.tar.

Eu gostaria de pegar essas linhas e executá-las xargs. Não sei o que é passado para o comando sendo executado. Como acesso o parâmetro no prompt (digamos que eu queira simplesmente repetir cada linha como cat file | xargs echo $PARAM) ou em um script bash.

Josh K
fonte
Não estou seguindo a pergunta, desculpe. Em particular, não tenho certeza do que significa "Não sei o que é passado para o comando que está sendo executado"
Michael Mrozek
11
@ Michael: Quando você executa uma lista, xargsela a divide por linha e alimenta cada linha em um comando, certo? Como faço para acessar isso se precisar dizer algo como cat file | xargs curl http://example.com/[PASSED FROM FILE].tar?
Josh K

Respostas:

70

A resposta de Michael está certa e deve resolver o seu problema. Corrida

cat file | xargs -I % curl http://example.com/persons/%.tar

fará o download dos arquivos bob.tar john.tar. sue.tarconforme o esperado.

MAS : gato aqui é inútil

prefiro usar:

<file xargs -I % curl http://example.com/persons/%.tar
Stefan
fonte
11
Na minha um exemplo de arquivo pode não ser ideal, no entanto,cat xaa xab xac xad ... xargs ...
Josh K
10
@ Josh Por alguma razão, as pessoas tendem a levar a sério o uso desnecessário de gatos aqui; Já fui votado duas vezes contra isso agora
Michael Mrozek
2
para o registro, você recebeu um +1 de mim. Acho que usando caté bom realmente, assim como para adicionar mais informações ... :)
Stefan
Certamente deveria ser xargs -I % curl …( opção xargs anterior curle suas opções / argumentos). No mínimo xargs curl -I %(onde -I %deve ser uma opção para xargs , não enrolar ) não é portátil.
Chris Johnsen
@ Chris, boa captura, tnx. fixo.
Stefan
16

Eu acho que você está perguntando como inserir as linhas individuais extraídas de xargs'stdin no meio de um comando, em vez de apenas colar no final sempre. Nesse caso, a -Ibandeira aceita um replacement-stringargumento; xargssubstituirá replacement-stringno comando a linha lida de stdin:

$ cat file | xargs -I foobar curl http://example.com/foobar.tar
Michael Mrozek
fonte
Ok, que tal curl http://example.com/foobar.tar > foobar.tar?
Josh K
2
@ Jos K: >é um shell constrói, e não vai funcionar xargs. Por outro lado, curl -ogravará em um arquivo nomeado em vez de stdout, como o que wgetfaz, então é provavelmente o que você gostaria de usar aqui.
#
9
$ man xargs
...
       --arg-file = arquivo
       -um arquivo
              Leia itens do arquivo em vez da entrada padrão. Se você usar isso
              opção, stdin permanece inalterado quando os comandos são executados. De outros-
              sábio, stdin é redirecionado de / dev / null.
...

Você pode querer set --delimiter=/ -da '\n'bem.


Por outro lado, se você está apenas tentando transformar cada linha do arquivo em um URL,

$ Sed arquivo: -e '//example.com/persons/&.tar# s # * # http.'

vai fazer, e se você quiser buscar todos eles, basta inseri-lo .| wget -i

efémero
fonte
8

outra maneira com o loop de shell:

for i in `cat file`; do curl -I http://foo.com/$i; done

você também pode executar cada iteração em segundo plano anexando &antes do último ponto e vírgula - para downloads muito grandes, isso pode ser útil

Brad Clawsie
fonte
2
Você se apaixonou por um dos erros clássicos ! <- link quebrado, aqui está uma versão em cache: Uso inútil do Cat Award .
Sorpigal
@Sorpigal Esse URL está quebrado. O que é o 'erro clássico'?
Starbeamrainbowlabs
@starbeamrainbowlabs - uso inútil de gato, coloquei uma versão em cache desse link no comentário acima.
Slm
@starbeamrainbowlabs: eu especificamente estava ligando para Backticks perigosas , mas o uso de gato também é desnecessário se você mudar para um enquanto construção:while IFS= read i ; do curl ... ; done < file
Sorpigal
3

Com o GNU Parallel, você pode:

cat urls | parallel curl {} ">" {/}

Ou:

cat persons | parallel curl http://example.com/persons/{}.tar ">" {}.tar

Assista ao vídeo de introdução do GNU Parallel para saber mais: http://www.youtube.com/watch?v=OpaiGYxkSuQ

Ole Tange
fonte
1

while read VAR; do ... done loop é simples, mas muito versátil:

while read word; do wget http://example.com/persons/$word; done < file
musiphil
fonte
0

Esta é uma versão mais geral da resposta de Stefan: s, mas estou usando o awk no meio para preparar a "string" exata que eu gostaria que o xargs execute. E então o xargs está usando o bash para fazer o "trabalho" real.

É um pouco exagerado para este exemplo, mas é uma solução geral que, com algumas modificações, pode resolver muitos problemas ...

cat file | awk '{print "curl http://example.com/persons/"$1".tar"}' | xargs -0 bash -c
Johan
fonte