O exemplo cat foo bar
não é o que eu quis dizer. Aqui cat
tem apenas uma entrada e uma saída de cada vez.
tee
é um exemplo: ela é enviada para todos os argumentos, além de sua saída padrão ao mesmo tempo. Usando o mesmo tipo de diagrama de arte ASCII como em minha resposta anterior , veja como o tee foo bar
se parece quando está operando em um terminal.
+------------------+
| tee |
===|<stdin | +------------+
→ | | | terminal |
| stdout>|=========|<input |
| | → ##==|< |
| | || +------------+
| stderr>|=====##
| | →
| | +-------------+
| 3>|=======|> file "foo" |
| | → +-------------+
| | +-------------+
| 4>|=======|> file "bar" |
| | → +-------------+
| |
+------------------+
Neste exemplo, tee
está enviando saída “útil” para três canais: para o terminal (porque é onde sua saída padrão está conectada) e para dois arquivos. Além disso, tee
tem mais um canal de saída para erros.
Um programa normalmente tem três canais de entrada / saída, identificados pelo seu descritor de arquivo número:
- entrada padrão (stdin para abreviar, descritor de arquivo numero 0);
- saída padrão (stdout para abreviar, descritor de arquivo número 1);
- erro padrão (stderr para breve, descritor de arquivo número 2).
O propósito dos descritores de arquivo 0, 1 e 2 é apenas uma questão de convenção - nada reforça que um programa não pode tentar escrever no descritor de arquivo 0 ou ler dos descritores 1 e 2 - mas esta é uma convenção que é basicamente universalmente seguido.
Se você executar um programa a partir de um terminal, os descritores de arquivo 0, 1 e 2 começarão a ser conectados a esse terminal, a menos que tenham sido redirecionados. Outros descritores de arquivos começam fechados e serão usados se o programa abrir outros arquivos.
Em particular, todos os comandos têm duas saídas: saída padrão (para a carga útil do comando, a saída “útil”) e erro padrão (para mensagens de erro ou informativas).
Um pipeline no shell ( command1 | command2 | command3 | …
) conecta a saída padrão de cada comando à entrada padrão do próximo comando. O erro padrão de todos os comandos vai para o terminal (a menos que seja redirecionado).
Os shells fornecem maneiras de redirecionar outros descritores de arquivos. Você provavelmente encontrou 2>&1
ou 2>file
para redirecionar o erro padrão. Vejo
Quando você usaria um descritor de arquivo adicional? e os outros posts com links para exemplos de manipulações de outros descritores de arquivos.
Shells ricos em recursos também oferecem substituição de processos para generalizar o redirecionamento de arquivos para comandos canalizados, para que você não seja limitado para um pipe linear com cada comando com uma única entrada e uma única saída.
Poucos comandos tentam acessar os descritores de arquivo acima de 2, exceto depois de abrirem um arquivo (a abertura de um arquivo escolhe um descritor de arquivo livre e retorna seu número para o aplicativo). Um exemplo é o GnuPG, que espera ler os dados para criptografar / decodificar / assinar / verificar em sua entrada padrão e gravar o resultado na saída padrão. Pode ser dito para ler uma senha em um descritor de arquivo diferente com a opção --passphrase-fd
. O GnuPG também tem opções para relatar dados de status em outros descritores de arquivos, para que você possa ter a saída da carga útil no stdout, as mensagens de erro no stderr e as informações de status em outro descritor de arquivo. Veja um exemplo em que a saída de um comando canalizado é usada como uma frase secreta:
echo fjbeqsvfu | rot13 | gpg -d --passphrase-fd=3 3<&0 <file.encrypted >file.plaintext