Como mesclar e canalizar resultados de dois comandos diferentes para um único comando?

28

Eu quero mesclar (união) a saída de dois comandos diferentes e canalizá-los para um único comando.

Um exemplo bobo:

Comandos Quero mesclar a saída:

cat wordlist.txt
ls ~/folder/*

para:

wc -l

Neste exemplo, se wordlist.txt contiver 5 linhas e 3 arquivos, eu quero que wc -l retorne 8.

$cat wordlist.txt *[magical union thing]* ls ~/folder/* | wc -l
8

Como faço isso?

    
por David Oneill 07.05.2012 / 21:05

3 respostas

41

Sua coisa da união mágica é um ponto-e-vírgula ... e chaves:

    { cat wordlist.txt ; ls ~/folder/* ; } | wc -l

Os parênteses agrupam apenas os comandos, de modo que o sinal de canal | afeta a saída combinada.

Você também pode usar o parêntese () em torno de um grupo de comando, o que executaria os comandos em um subshell. Isto tem um conjunto subtil de diferenças com chaves, e. tente o seguinte:

    cd $HOME/Desktop ; (cd $HOME ; pwd) ; pwd
    cd $HOME/Desktop ; { cd $HOME ; pwd ; } ; pwd

Você verá que todas as variáveis ​​de ambiente, incluindo o diretório de trabalho atual, são redefinidas após sair do grupo de parênteses, mas não depois de sair do grupo de chaves.

Quanto ao ponto-e-vírgula, as alternativas incluem os sinais && e || , que executarão condicionalmente o segundo comando somente se o primeiro for bem-sucedido ou se não for, respectivamente, por exemplo

    cd $HOME/project && make
    ls $HOME/project || echo "Directory not found."
    
por pablomme 07.05.2012 / 21:09
8

Como wc aceita um caminho de arquivo como entrada, você também pode usar a substituição de processo:

wc -l <(cat wordlist.txt; ls ~/folder/*)

Isso é equivalente a:

echo wordlist.txt > temp
ls ~/folder/* >> temp
wc -l temp

Lembre-se de que ls ~/folder/* também retorna o conteúdo dos subdiretórios, se houver algum (devido à expansão glob). Se você quiser apenas listar o conteúdo de ~/folder , use apenas ls ~/folder .

    
por Lekensteyn 07.05.2012 / 21:10
0

Eu estava me fazendo a mesma pergunta e acabei escrevendo um pequeno roteiro.

magicalUnionThing (eu chamo de append ):

#!/bin/sh
cat /dev/stdin
$*

Torne esse script executável

chmod +x ./magicalUnionThing

Agora você faz

cat wordlist.txt |./magicalUnionThing ls ~/folder/* | wc -l

O que faz:

  • Enviar entrada padrão para saída padrão
  • Executar argumento. $* retorna todos os argumentos como uma string. A saída desse comando vai para a saída padrão do script por padrão.

Assim, o stdout do magicalUnionThing será seu stdin + stdout do comando que é passado como argumento.

Existem formas mais simples, como outras respostas.
Talvez essa alternativa possa ser útil em alguns casos.

    
por Rolf 11.03.2018 / 12:17