Aproveite o mês das
carreiras na Alura

Até 44% OFF

Falta pouco!

00

DIAS

00

HORAS

00

MIN

00

SEG

Lendo e escrevendo arquivos com redirecionamento no Shell

Alura
Gabriel de Russo e Carmo
Gabriel de Russo e Carmo

Compartilhe

Sou monitor de um professor na faculdade e uma das minhas tarefas é corrigir alguns trabalhos.

A turma tem uns 40 alunos e eles farão 3 trabalhos ao longo do semestre. No final do curso, preciso fazer um relatório para o professor, indicando quais alunos estão de recuperação, reprovados ou aprovados.

Rapidamente fiz um programa em Python que lê uma lista de alunos e suas notas e imprime na tela a situação de cada um. O código ficou mais ou menos assim:


import sys
for linha in sys.stdin:
  linha = linha.split(';') 
  aluno = linha[0] 
  trabalho1 = int(linha[1])
  trabalho2 = int(linha[2]) 
  trabalho3 = int(linha[3]) 
  media = (trabalho1 + trabalho2 + trabalho3) / 3 print(aluno + ': ', end='') 
    if media >= 5: print('Aprovado') 
        elif media >= 3: print('Recuperação') 
    else: print('Reprovado')

Não tem problema se você não manja de Python, o importante aqui é entender que esse código lê várias linhas do teclado na forma:

 Nome do aluno;
 Nota1;
 Nota2;
 Nota3

E imprime na tela algo como:

 Nome do aluno: Aprovado

A execução do código é a seguinte:

 $ python media.py > João da Silva;8;7;9 João da Silva: Aprovado > Larissa Souza;10;9;10 Larissa Souza: Aprovado > Mario Oliveira;5;4;5 Mario Oliveira: Recuperação > Pedro Carvalho;3;0;1 Pedro Carvalho: Reprovado

Embora o programa funcione, existem alguns detalhes que ainda dificultam a rotina de gerar o relatório, vamos entender quais são:

  • O programa imprime imediatamente depois que digito, deixando o resultado final confuso.
  • Dá muito trabalho rodar de novo. Se eu esquecer de um aluno, preciso digitar 40 nomes com 3 notas cada de novo.

Se o programa lesse os alunos e notas de um arquivo, daria para modificar só uma linha facilmente. Uma opção é alterar o código para trabalhar com arquivos. Essa alternativa é viável porque o código é meu e eu sei trabalhar com Python. Ficaria mais ou menos assim:


arquivo = open('notas.txt', 'r') #abrindo arquivo
for linha in arquivo: #lendo do arquivo linha = linha.split(';') aluno = linha\[0\] ... ```
# Entendendo o redirecionamento
Nem sempre temos o luxo de ter acesso ao código fonte dos programas que usamos. Então como podemos fazer para ler as informações de um arquivo e direcionar cada linha para o nosso programa sem mexer no código?
Em sistemas baseados no Unix (como é o caso do Linux e do Mac), todos os programas são associados a uma **entrada e saída padrão**. Em geral, a entrada é o teclado e a saída é a tela (terminal). Podemos **redirecionar** tanto a entrada quanto a saída padrão de qualquer programa sem mexer no código, podendo facilmente ler e escrever em arquivos.
## Redirecionando a entrada
Para **redirecionar a entrada** do código original, basta utilizar o caractere `<` na hora de rodar o programa, indicando um arquivo de entrada. Então vamos criar o arquivo `notas.txt` com o conteúdo:

João da Silva;8;7;9 Larissa Souza;10;9;10 Mario Oliveira;5;4;5 Pedro Carvalho;3;0;1


Rodando o programa da seguinte forma:
```python
 $ python media.py < notas.txt João da Silva: Aprovado Larissa Souza: Aprovado Mario Oliveira: Recuperação Pedro Carvalho: Reprovado

O resultado já ficou muito melhor. Agora posso copiar e colar a saída e mandar para o professor tranquilamente. Também posso mudar o nome do arquivo a ser lido com facilidade.

Modificando o código para escrever num arquivo

Já melhorou bastante, porém estamos lidando apenas com 4 alunos. E se fossem 1000? Copiar 1000 linhas do terminal não é nada produtivo. Seria uma boa jogar a saída num arquivo também, certo?

Podemos fazer isso modificando o nosso código, da seguinte forma:


import sys
saida = open('resultado.txt', 'w') # abrindo arquivo de saida
for linha in sys.stdin:
 linha = linha.split(';') 
 aluno = linha[0] 
 trabalho1 = int(linha[1]) 
 trabalho2 = int(linha[2]) 
 trabalho3 = int(linha[3])
media = (trabalho1 + trabalho2 + trabalho3) / 3 saida.write(aluno + ': ') # escrevendo no arquivo 
    if media >= 5: saida.write('Aprovado\\n') # escrevendo no arquivo 
        elif media >= 3: saida.write('Recuperação\\n') # escrevendo no arquivo 
        else: saida.write('Reprovado\\n') # escrevendo no arquivo
saida.close() # fechando o arquivo de saida

Observe que modificamos algumas boas linhas de código. Meio trabalhoso, não acha?

Redirecionando a saída

Que tal utilizarmos o redirecionamento também? É muito mais cômodo porque não vamos mexer em código.

Para redirecionar a saída do código original, basta utilizar o caractere > na hora de rodar o programa, de forma semelhante ao redirecionamento da entrada:


$ python media.py > resultado.txt > João da Silva;8;7;9 > Larissa Souza;10;9;10 > Mario Oliveira;5;4;5 > Pedro Carvalho;3;0;1

E se olharmos o conteúdo de resultado.txt, veremos:

 João da Silva: Aprovado Larissa Souza: Aprovado Mario Oliveira: Recuperação Pedro Carvalho: Reprovado

Redirecionando entrada e saída ao mesmo tempo

Uma coisa legal sobre o redirecionamento é que podemos fazer uma combinação. Não há nenhum problema em redirecionar tanto a entrada quanto a saída, isto é, podemos realizar o redirecionamento de saída e entrada ao mesmo tempo, veja como:

 $ python media.py < notas.txt > resultado.txt

Quando fazemos esse redirecionamento o nosso programa primeiro lê o arquivo notas.txt e depois escreve em resultado.txt.

Truncamento

Agora os principais detalhes foram resolvidos, vou corrigir os trabalhos e gerar o relatório para o professor.

Como a turma é tanto para alunos do curso de Ciência da Computação como para alunos de Sistemas de Informação, decidi colocar as notas em dois arquivos diferentes: notas_cc.txt e notas_si.txt. Seus conteúdos são mais ou menos o seguinte:

notas_cc.txt Julia Aparecida;8;9;9 Gabriel Russo;2;4;2
notas_si.txt Danilo Gomes;10;9;10 Horacio Soares;5;7;4

Vou rodar meu programa duas vezes e meu relatório estará pronto:

 $ python media.py < notas_cc.txt > resultado.txt $ python media.py < notas_si.txt > resultado.txt

Olhando o conteúdo de resultado.txt:

 Danilo Gomes: Aprovado Horacio Soares: Aprovado

O que houve com os alunos de Ciência da Computação? Eles deveriam estar no arquivo também.

O problema é que quando redirecionamos a saída de um programa para um arquivo, o sistema operacional trunca o arquivo antes, isto é, apaga todo seu conteúdo. Não é isso que queremos... E agora?

Podemos redirecionar a saída com os caracteres >>, que fazem exatamente a mesma coisa com a diferença de que o arquivo não é truncado. Veja:

 $ python media.py < notas_cc.txt > resultado.txt $ python media.py < notas_si.txt >> resultado.txt

Na primeira vez, truncamos o arquivo e escrevemos. Na segunda, apenas escrevemos. Olhando para o conteúdo de resultado.txt vemos:

 Julia Aparecida: Aprovado Gabriel Russo: Reprovado Danilo Gomes: Aprovado Horacio Soares: Aprovado
Banner da Imersão de IA da Alura com Google Gemini. Participe de aulas gratuitas online com certificado. Domine as inovações mais recentes da IA.

Para saber mais

Além de ler e escrever em arquivos, com esses redirecionamentos é possível fazer os programas conversarem, ou seja, podemos redirecionar a saída de um programa para a entrada de outro.

O programa ps com a flag -x imprime todos os processos que estão rodando nesse momento. Muitas vezes, esta lista é enorme e fica muito difícil procurar um processo. Podemos utilizar o programa grep para filtrar esses resultados.

O grep funciona de várias formas, mas uma delas é procurar um texto na entrada. Mas como redirecionar a saída do ps para a entrada do grep ?

Poderíamos utilizar um arquivo para guardar a saída e depois utilizá-lo como entrada, porém podemos fazer isso diretamente utilizando o caractere | (chama-se pipe). Basicamente, pegamos a saída padrão de um programa e jogamos para a entrada padrão de outro. Vamos ver um exemplo:

 $ ps -x | grep Eclipse 41891 ?? 0:37.48 /Users/gabriel/Applications/Eclipse.app/Contents/MacOS/eclipse

Agora que eu sei que meu processo tem o PID 41891, eu posso rodar kill 41891 para fechar o Eclipse travado.

Resumindo

Nesse post aprendemos que é possível ler e escrever em arquivos sem precisar mexer no código de nossos programas. Para fazer isso, utilizamos os seguintes redirecionamentos:

  • < para redirecionar a entrada
  • > para redirecionar a saída truncando (apagando) o arquivo
  • >> para redirecionar a saída sem truncar o arquivo

Que tal aprender mais sobre o Shell e Linux no geral? Aqui na Alura temos diversos cursos online de Linux para você aprender desde a estrutura básica do Linux como também os principais programas e comandos desse sistema operacional.

Veja outros artigos sobre DevOps