Redirecionamentos no Bash
Curso de Bash
Seção do curso sobre redirecionamentos.
Entrada padrão (ou o acrônimo em inglês stdin) é um dos 3 canais de comunicação padrão entre um processo e seu ambiente. Nesse canal os dados são originados no ambiente e trafegam em destino ao processo.
É dito que um programa lê dados da entrada padrão quando digitamos os caracteres em um terminal (ou outro ambiente) e tais caracteres são buscados pelo programa.
Saída padrão (stout) é o destino dos dados produzidos por um processo. Tipicamente conectado ao terminal.
Erro padrão (stderr) também é um canal de saída, mas é utilizado apenas para dar saída às mensagens de erro.
Conteúdo
Origem da entrada padrão
A entrada padrão é representada pelo descritor de arquivo 0 (do inglês, file descriptor), que é um link com o caminho /proc/<PID>/fd/0, onde <PID> é substituído pelo PID do processo.
Por padrão esse link aponta para um arquivo que representa um terminal.
O comando tty exibe o nome do arquivo que representa o terminal.
tty/dev/pts/1Abaixo podemos verificar que a entrada padrão do processo com PID 5311 está conectada ao terminal /dev/pts/1.
ls -l /proc/5311/fd/0lrwx------ 1 caio caio 64 Dec 6 10:00 /proc/5311/fd/0 -> /dev/pts/1Lendo dados da entrada padrão
- pode ser utilizado como argumento para que o comando suportado leia dados da entrada padrão.
Vários dos comandos, especialmente para processamento de texto, aceitam - como argumento geralmente no lugar que seria de um arquivo de texto.
O argumento - facilita a entrada de dados já que linhas podem ser digitadas diretamente no terminal, evitando assim a criação de um arquivo.
- é opcional quando nenhum outro argumento é especificado. shuf, sort, cat, tac, head, tail, wc são exemplos de comandos que leem da entrada padrão quando nenhum argumento é especificado ou quando - é especificado.
shufLogo após digitarmos o nome do comando e pressionarmos Enter, o cursor é movido para a linha seguinte. A partir daí qualquer caractere digitado fará parte da entrada, incluíndo o caractere novalinha que é inserido quando pressionamos Enter.
Ctrl + D envia um caractere chamado EOF ou End of File (fim do arquivo, em português) para indicar o término da entrada. Ctrl + D deve ser pressionado uma vez quando o cursor está em uma linha vazia e duas vezes quando há caracteres na linha.
Assim que terminada a entrada de dados o comando é executado.
Na entrada abaixo Ctrl + D é representado por ^D apenas para ilustrar o conceito, o atalho não é exibido.
Z
D
F
H
^D
A saída inicia na linha em que Ctrl + D foi pressionado.
H
Z
F
D
- é necessário quando há outros argumentos. > abaixo indica as linhas digitadas pois a entrada e saída estão intercaladas.
head -n 2 /etc/hosts -==> /etc/hosts <==
127.0.0.1 localhost
127.0.1.1 FX505DV
==> standard input <==
> A
A
> B
B
Redirecionamento de entrada
É representado por < e redireciona a entrada padrão para o arquivo (ou outro recurso) à sua direita.
O arquivo letras é criado abaixo contendo as letras de A até D, cada uma em uma linha.
printf "%s\n" {A..D} > letrasA entrada padrão de wc é redirecionada para o arquivo letras.
< letras wc4 4 8O uso abaixo, com o redirecionamento à direita do comando, tem efeito idêntico e é a forma mais comum.
wc < letras4 4 8Here Documents
Tipo de redirecionamento da entrada padrão que permite especificar as linhas diretamente no terminal.
É especificado com o operador << <palavra> onde <palavra> é a sequência que determina o fim da entrada.
Difere de - pois a entrada é terminada com <palavra> ao invés de Ctrl + D.
O operador << abaixo determina que a linha contendo fim, sem nenhum caractere o precedendo ou sucedendo, encerra o here-document.
tr -d "[:digit:]" << fim
A1B2
C3
fim 4
fim
Saída
AB
C
fim
Expansão de variável, substituição de comando e expansão aritmética também são interpretadas (conceitos abordados em capítulos futuros).
tac << ultima_linha
Número aleatório $RANDOM
Diretório atual $(pwd)
Exponenciação $(( 2 ** 10))
ultima_linha
Saída
Exponenciação 1024
Diretório atual /home/caio
Número aleatório 315
Para evitar qualquer expansão basta colocar o delimitador entre "" ou ''. Contudo o delimitador da última linha da entrada deve aparecer sem as aspas.
tac << "ultima_linha"
Exponenciação $(( 2 ** 10))
Diretório atual $(pwd)
Número aleatório $RANDOM
ultima_linha
⚠️ Ctrl + D na entrada padrão ocasiona um aviso na saída apesar de processar todas as linhas posteriores.
tr "[:lower:]" "[:upper:]" << termino> Uma linha
> ^D
> bash: warning: here-document at line 43 delimited by end-of-file (wanted `termino')
UMA LINHA
Here Strings
O operador <<< realiza o redirecionamento da entrada padrão para a palavra à sua direita. A palavra é chamada de here_string.
wc <<< A1 1 2❌ Especificar mais de um operando é um erro. Bash interpreta as palavras adicionais como argumentos.
wc <<< A B Cwc: B: No such file or directory
wc: C: No such file or directory
0 0 0 total
Aspas podem ser utilizadas para esse fim.
wc <<< "A B C"1 3 6Aspas também podem ser utilizadas para inserir novalinha na here-string.
wc -l <<< "A
B C"
2Expansão de variável, substituição de comando e expansão aritmética são interpretadas na here-string. Conceitos abordados em capítulos futuros.
cat <<< "$BASH_VERSION $(date) $((~-2))"5.0.17(1)-release Sun 06 Dec 2020 17:25:30 -03 1Redirecionamento da saída
Assim como a entrada padrão, a saída padrão e o erro padrão são tipicamente conectados ao terminal.
tty/dev/pts/1Saída padrão tem o descritor de arquivo 1 e o erro padrão 2.
ls -l /proc/5080/fdlrwx------ 1 caio caio 64 Dec 7 09:25 0 -> /dev/pts/1
lrwx------ 1 caio caio 64 Dec 7 09:25 1 -> /dev/pts/1
lrwx------ 1 caio caio 64 Dec 7 09:25 2 -> /dev/pts/1
O operador de redirecionamento > redireciona a saída do comando para o arquivo à sua direita. Caso o arquivo não exista, é criado. Caso já exista é sobrescrito.
O comando date tem sua saída redirecionada para o arquivo data_e_hora e então o arquivo tem seu conteúdo exibido por head.
date > data_e_hora
head data_e_hora
Mon 07 Dec 2020 10:22:08 -03Caso utilizemos o arquivo novamente como operando de >, ele será sobrescrito.
ps > data_e_hora
head data_e_hora
PID TTY TIME CMD
5080 pts/1 00:00:00 bash
9766 pts/1 00:00:00 ps
Já o operador >> insere a saída ao fim do operando (o arquivo à sua direita). Caso o arquivo não exista, é criado.
whoami >> data_e_hora PID TTY TIME CMD
5080 pts/1 00:00:00 bash
9766 pts/1 00:00:00 ps
caio
Além de arquivos comuns, é possível utilizar arquivos especiais como abaixo, em que a saída é redirecionada para outro terminal.
groups > /dev/pts/2Saída no terminal /dev/pts/2, logo após o prompt.
caio@FX505DV:~/temp$ caio adm cdrom sudo dip plugdev lpadmin lxd sambashareRedirecionamento de erro padrão
2> e 2>> redirecionam as mensagems de erro como os operadores > e >> fazem com a saída regular.
ls /inexistente 2> errors
tail erros
ls: cannot access '/inexistente': No such file or directoryÉ possível ignorar as mensagens de erro ou mesmo a saída padrão redirecionando-as para /dev/null.
mkdir -v . .. um_dir 2> /dev/nullmkdir: created directory 'um_dir'Mais de um redirecionamento pode ser especificado para um mesmo comando.
Abaixo cat envia para a saída padrão (redirecionada para o meu_arquivo) o que foi lido da entrada padrão (redicionada para a Uma linha) e tail exibe o conteúdo do recém criado meu_arquivo.
cat > meu_arquivo <<< "Uma linha"
tail meu_arquivo
Uma linhaRedirecionando erro e saída padrão simultaneamente
O operador &> redireciona ambas as saídas (saída padrão e erro padrão) para o arquivo à direita. O arquivo é criado caso não exista e sobrescrito caso exista, como ocorre com > e 2>.
mkdir -v .. . dir1 dir2 &> saidas
head saidas
mkdir: cannot create directory ‘..’: File exists
mkdir: cannot create directory ‘.’: File exists
mkdir: created directory 'dir1'
mkdir: created directory 'dir2'
Verificando os descritores de arquivo
No primeiro terminal inicie nova sessão de Bash redirecionando sua saída e erro padrão para o arquivo historico.
bash &> historicoNo segundo terminal execute tail -F para acompanhar as inserções de linha.
tail -F historicoDe volta ao primeiro, execute o comando abaixo para obter o PID da sessão de Bash.
echo $$PID exibido na saída no segundo terminal.
29316Ainda no primeiro terminal, exiba os descritores de arquivo para a sessão de Bash.
ls -l /proc/29316/fdSaída no segundo.
29316
total 0
lrwx------ 1 caio caio 64 Dec 7 15:26 0 -> /dev/pts/1
l-wx------ 1 caio caio 64 Dec 7 15:26 1 -> /home/caio/historico
l-wx------ 1 caio caio 64 Dec 7 15:26 2 -> /home/caio/historico
Ctrl + D no primero para sair da sessão de Bash e Ctrl + C no segundo para interromper tail.