Passando um argumento para vários comandos em uma única linha

10

Eu gostaria de poder executar vários comandos no mesmo arquivo em uma única linha. A maneira como atualmente faço isso é:

commandA file && commandB file && perl -ne '...' file

Meu instinto me diz que deve haver uma maneira de fornecer o argumento do nome do arquivo apenas uma vez e canalizá-lo para os dois comandos simultaneamente xargsou algo semelhante:

find file | xargs commandA && xargs commandB && xargs perl -ne '...'

Quando tento isso, apenas o primeiro comando é executado. Como posso conseguir o que quero fazer?

Zaid
fonte

Respostas:

12

Você pode definir uma variável local para isso:

f=file; commandA $f && commandB $f && ...

Você também pode executar todos incondicionalmente (substituindo &&por ;) ou em paralelo (substituindo &&por &).

Como alternativa, você também pode usar a expansão do histórico do shell para referenciar argumentos anteriores:

commandA file && commandB !:1 && ...
maxschlepzig
fonte
Não é exatamente o que eu tinha em mente, mas é uma alternativa interessante.
Zaid
O que há de errado com esta resposta?
Chris
Isso é muito legal! Existe uma maneira de não definir uma nova variável?
usuário
@ usuário, eu adicionei uma alternativa.
maxschlepzig
8

Para shells como Bash, Korn e Z que têm substituição de processo, você pode fazer isso:

find file | tee >(xargs commandA) >(xargs commandB) >(xargs perl -ne '...')
Pausado até novo aviso.
fonte
2

Você pode usar xargs para construir uma linha de comando, por exemplo:

echo file | xargs -i -- echo ls -l {}\; wc -l {}

Basta colocar o acima no bash para executá-lo:

echo file | xargs -i -- echo ls -l {}\; wc -l {} | bash

Estendendo o exemplo para todos os arquivos * .c no diretório atual (escapando do ls aqui para impedir qualquer substituição de alias do shell):

\ls -1 *.c | xargs -i -- echo ls -l {}\; wc -l {} | bash
frielp
fonte
Usou isso para obter uma listagem de todos os arquivos contidos em diretórios onde o nome é como "enumerações": find . -name "*enums*" | xargs -i echo -e echo {}\; ls -lh {}\; echo -e '\n\n' | bash
Matt Lachman
1

Eu não votaria nisso. É bobo e perigoso, mas apenas no interesse de listar as maneiras de fazer isso, há:

for cmd in "commandA" "commandB" "perl -ne '...'" ; do eval $cmd file ; done

frabjous
fonte