Existem alguns comandos que filtram ou agem na entrada e, em seguida, transmitem-na como saída, penso eu normalmente stdout
- mas alguns comandos simplesmente aceitam stdin
e fazem o que fazem com ela e não produzem nada.
Estou mais familiarizado com o OS X e, portanto, existem dois que vêm à mente imediatamente pbcopy
e pbpaste
- que são meios de acessar a área de transferência do sistema.
De qualquer forma, eu sei que se eu quiser pegar o stdout e cuspir a saída para ir para o stdout
arquivo e para os dois, então posso usar o tee
comando E eu sei um pouco xargs
, mas acho que não é isso que estou procurando.
Quero saber como posso dividir stdout
para ir entre dois (ou mais) comandos. Por exemplo:
cat file.txt | stdout-split -c1 pbcopy -c2 grep -i errors
Provavelmente, há um exemplo melhor do que esse, mas estou realmente interessado em saber como posso enviar stdout para um comando que não o retransmite e, ao mesmo tempo, stdout
não seja "silenciado" - não estou perguntando sobre como cat
um arquivo e grep
parte dele e copie-o para a área de transferência - os comandos específicos não são tão importantes.
Além disso - não estou perguntando como enviar isso para um arquivo e stdout
- isso pode ser uma pergunta "duplicada" (desculpe), mas fiz algumas pesquisas e só consegui encontrar perguntas semelhantes que estavam perguntando sobre como dividir entre stdout e um arquivo - e as respostas para essas perguntas pareciam ser tee
, o que acho que não funcionará para mim.
Finalmente, você pode perguntar "por que não fazer do pbcopy a última coisa na cadeia de tubos?" e minha resposta é 1) e se eu quiser usá-lo e ainda ver a saída no console? 2) e se eu quiser usar dois comandos que não saem stdout
depois que eles processam a entrada?
Ah, e mais uma coisa - eu sei que eu poderia usar tee
e um pipe nomeado ( mkfifo
), mas eu esperava uma maneira de que isso pudesse ser feito em linha, de forma concisa, sem uma configuração prévia :)
Respostas:
Você pode usar
tee
e processar a substituição para isso:Isso enviará toda a saída de
cat file.txt
parapbcopy
e você só obterá o resultadogrep
no seu console.Você pode colocar vários processos na
tee
peça:fonte
pbcopy
, mas vale a pena mencionar em geral: qualquer que seja a saída de substituição do processo, também é vista pelo próximo segmento de tubulação, após a entrada original; por exemplo:seq 3 | tee >(cat -n) | cat -e
(cat -n
numera as linhas de entrada,cat -e
marca novas linhas$
; você verá quecat -e
é aplicado à entrada original (primeiro) e (depois) à saída decat -n
). A saída de várias substituições de processo chegará em ordem não determinística.>(
único funcionabash
. Se você tentar usar isso, por exemplosh
, não funcionará. É importante fazer esse aviso.dash
, que atua comosh
no Ubuntu, não é compatível e até o próprio Bash desativa o recurso quando invocado comosh
ou quandoset -o posix
está em vigor. No entanto, não é apenas Bash que suporta substituições de processos:ksh
ezsh
apoiá-los também (não tenho certeza sobre outros).bash
eksh
-zsh
aparentemente não enviar a saída de substituições de processo de saída através do pipeline (sem dúvida, é preferível , porque não poluem o que é enviado para o segmento de pipeline próxima - embora ainda imprime ). Em todas as shells mencionadas, no entanto, geralmente não é uma boa idéia ter um único pipeline no qual a saída stdout e a saída regulares de substituições de processo sejam misturadas - a ordem da saída não será previsível, de uma maneira que só possa aparecer com pouca frequência ou com grande volume. conjuntos de dados de saída.Você pode especificar vários nomes de arquivos
tee
e, além disso, a saída padrão pode ser canalizada em um comando. Para despachar a saída para vários comandos, você precisa criar vários pipes e especificar cada um deles como uma saída detee
. Existem várias maneiras de fazer isso.Substituição de processo
Se seu shell for ksh93, bash ou zsh, você poderá usar a substituição de processo. Essa é uma maneira de passar um canal para um comando que espera um nome de arquivo. O shell cria o canal e passa um nome de arquivo como
/dev/fd/3
para o comando O número é o descritor de arquivo ao qual o canal está conectado. Algumas variantes do unix não suportam/dev/fd
; nesses, um pipe nomeado é usado (veja abaixo).Descritores de arquivo
Em qualquer shell POSIX, você pode usar vários descritores de arquivo explicitamente. Isso requer uma variante unix compatível
/dev/fd
, pois todas, exceto uma das saídas de,tee
devem ser especificadas pelo nome.Canais nomeados
O método mais básico e portátil é usar pipes nomeados . A desvantagem é que você precisa encontrar um diretório gravável, criar os pipes e limpar depois.
fonte
tee "$tmp_dir/f1" "$tmp_dir/f2" | command3
certamente deve sercommand3 | tee "$tmp_dir/f1" "$tmp_dir/f2"
, como você quer que sejacommand3
canalizadotee
, não? Testei sua versãodash
etee
bloqueia indefinidamente a espera de entrada, mas alternar a ordem produziu o resultado esperado.command
,command2
ecommand3
.<command> | bash -c 'tee >(command1) >(command2) | command3'
. Isso ajudou no meu caso.Basta jogar com a substituição do processo.
grep
são dois binários que têm a mesma saída damycommand_exec
entrada específica do processo.fonte
Se você estiver usando
zsh
, poderá tirar proveito do poder doMULTIOS
recurso, ou seja, livrar-setee
completamente do comando:apenas gravará a saída de
uname
dois arquivos diferentes:file1
efile2
, o que é equivalente auname | tee file1 >file2
Da mesma forma, o redirecionamento de entradas padrão
é equivalente a
cat file1 file2 | wc -l
(observe que isso não é o mesmo quewc -l file1 file2
, mais tarde conta o número de linhas em cada arquivo separadamente).Obviamente, você também pode usar
MULTIOS
para redirecionar a saída não para arquivos, mas para outros processos, usando a substituição de processos, por exemplo:fonte
MULTIOS
é uma opção que está ativada por padrão (e pode ser desativada comunsetopt MULTIOS
).Para uma saída razoavelmente pequena produzida por um comando, podemos redirecionar a saída para um arquivo temporário e enviar esse arquivo temporário para comandos em loop. Isso pode ser útil quando a ordem dos comandos executados for importante.
O script a seguir, por exemplo, pode fazer isso:
Teste executado no Ubuntu 16.04 com
/bin/sh
comodash
shell:fonte
Capture o comando
STDOUT
para uma variável e reutilize-o quantas vezes quiser:Se você precisar capturar
STDERR
também, use2>&1
no final do comando, assim:fonte
Isso pode ser útil: http://www.spinellis.gr/sw/dgsh/ (shell de gráfico direcionado) Parece uma substituição do bash que suporta uma sintaxe mais fácil dos comandos "multipipe".
fonte
Aqui está uma solução parcial rápida e suja, compatível com qualquer shell, inclusive
busybox
.O problema mais restrito que ele resolve é: imprima o completo
stdout
em um console e filtre-o em outro, sem arquivos temporários ou pipes nomeados.tty
. Vamos assumir/dev/pty/2
.the_program | tee /dev/pty/2 | grep ImportantLog:
Você obtém um log completo e um filtrado.
fonte