Shell UNIX

Caminhos, expansão de nomes, redirecionamentos, pipes, processos e consulta do manual.

TLDR

Perguntar sobre esta página

ChatGPTClaudePerplexityGrokGeminiCopiar e abrirDeepSeekCopiar e abrir

A linha sort -n < numeros.txt | uniq > distintos.txt envolve três tarefas diferentes: a shell abre os ficheiros e liga os canais, sort ordena os números e uniq elimina repetições adjacentes. A shell interpreta comandos e argumentos e prepara a entrada e a saída dos programas. Para prever o resultado, acompanha primeiro essa preparação e depois os bytes que cada programa recebe.

Caminhos e diretório de trabalho

Um caminho absoluto começa em /, a raiz. Um relativo começa no diretório de trabalho. . designa esse diretório e .. o seu pai. ~ expande para a pasta pessoal quando usado numa posição apropriada da linha de comando.

mkdir -p treino/a/b
cd treino/a/b
pwd
cd ../..
pwd

Depois do primeiro cd estás em treino/a/b; ../.. sobe dois níveis até treino. O resultado absoluto de pwd depende da pasta onde começaste. cd sem argumento leva-te à pasta pessoal.

Expandir nomes e proteger texto

Supõe uma pasta com main.c, ajuda.c e notas.txt. A shell expande *.c para os dois nomes existentes que terminam em .c, antes de correr o comando. ? corresponde a um carácter e [ab] a um carácter do conjunto. As aspas protegem o texto contra certas expansões.

printf '%s\n' *.c
find . -name '*.c' -print

No primeiro comando, a shell procura os nomes na pasta corrente, ou seja a expansão acontece antes de printf correr. No segundo, as aspas entregam *.c ao find, que procura na árvore. Sem aspas, o padrão pode ser expandido cedo e dar argumentos diferentes dos pretendidos.

Aspas simples conservam o texto literal. Aspas duplas conservam espaços, mas ainda permitem expansões como $HOME. A expansão {a,b} da Bash produz duas alternativas de texto, mesmo que os ficheiros não existam. Um glob não é uma expressão regular: o * de grep tem outro significado.

Três canais e redirecionamento

Um processo costuma começar com os descritores 0, 1 e 2 abertos, respetivamente entrada padrão, saída padrão e erros padrão. Na biblioteca C, as interfaces correspondentes são stdin, stdout e stderr, do tipo FILE *.

Operador da shellEfeito
< entrada.txtLiga a entrada padrão ao ficheiro
> saida.txtCria ou trunca o ficheiro e liga a saída padrão
>> saida.txtAcrescenta a saída no fim
2> erros.txtRedireciona os erros padrão
2>&1Faz o descritor 2 referir o destino atual do 1
a | bLiga a saída padrão de a à entrada padrão de b
printf '9\n2\n9\n5\n' > numeros.txt
sort -n < numeros.txt | uniq > distintos.txt
cat distintos.txt
EtapaBytes que seguem para a etapa seguinte
Entrada de sort9\n2\n9\n5\n
Saída de sort -n2\n5\n9\n9\n
Saída de uniq2\n5\n9\n

A saída final é 2, 5, 9, uma por linha. sort -n ordena numericamente e uniq elimina repetições adjacentes, por isso sem ordenar duas ocorrências separadas poderiam sobreviver.

A shell retira < numeros.txt da lista de argumentos de sort, por isso o programa recebe dados por stdin, não o texto <. Este detalhe explica por que um programa com argc == 1 ainda consegue ler um ficheiro redirecionado.

A ordem dos redirecionamentos importa. comando > tudo.txt 2>&1 envia os dois canais para o ficheiro. Em comando 2>&1 > saida.txt, stderr conserva o destino que stdout tinha antes de mudar.

Não uses sort ficheiro > ficheiro: a shell pode truncar o destino antes de sort o ler. Usa um destino diferente e, depois de confirmar o resultado, substitui o original.

Filtrar e contar

grep -v '^#' dados.txt | cut -d ':' -f 1 | sort
sed 's/erro/aviso/g' < registo.txt
head -n 3 dados.txt
tail -n 3 dados.txt

grep -v exclui linhas que correspondem ao padrão. cut escolhe campos usando : como separador. sed substitui todas as ocorrências por linha por causa de g. Estes comandos não alteram o ficheiro de entrada por si só.

wc -l conta caracteres de mudança de linha, não linhas visuais, ou seja printf abc | wc -l dá 0. wc -c conta bytes, por isso um carácter acentuado em UTF-8 pode ocupar mais de um byte.

Processos e jobs

comando & inicia um job sem a shell esperar pelo seu fim antes de apresentar outro prompt. O processo não fica automaticamente independente do terminal nem imune ao logout, porque continuas ligado à mesma sessão.

jobs mostra os jobs da shell e ps consulta os processos do sistema; ps -A | wc -l é apenas uma aproximação ao seu número, porque pode incluir um cabeçalho, os próprios programas da pipeline e alterações ocorridas enquanto os dados são recolhidos.

Ctrl+C costuma enviar SIGINT ao grupo em primeiro plano. Ctrl+Z costuma enviar SIGTSTP e fg retoma um job em primeiro plano. kill envia sinais, ou seja não significa sempre matar. Para pedires terminação, começa normalmente com SIGTERM, porque SIGKILL não permite limpeza pelo programa.

Manual, permissões e arquivo

man 2 open consulta uma chamada de sistema; man 3 fopen consulta uma função de biblioteca. SYNOPSIS mostra cabeçalhos e tipos. RETURN VALUE e ERRORS dizem como reconhecer falhas. command -v gcc mostra o comando que a shell encontra.

chmod 640 ficheiro dá leitura e escrita ao dono, leitura ao grupo e nada aos restantes. O equivalente simbólico é chmod u=rw,go-rwx,g+r ficheiro. Os dígitos são combinações de 4 para leitura, 2 para escrita e 1 para execução. Numa linha como -rw-r-----, o primeiro carácter indica ficheiro regular e os nove seguintes dão as permissões de dono, grupo e outros. Num diretório, execução permite atravessar nomes; leitura permite listar entradas. Apagar uma entrada depende das permissões do diretório que a contém. A data habitual de ls -l é a última modificação, não a criação do ficheiro.

tar -czf treino.tar.gz treino
tar -tzf treino.tar.gz

O primeiro comando cria um arquivo comprimido e o segundo lista-o sem o extrair. Para exercícios que removem ou substituem ficheiros, trabalha numa pasta de treino e confirma pwd antes do comando.

Exercícios

Argumentos depois da shell

Executas ./programa 7 < dados.txt. Indica argc, argv[1] e a origem da entrada padrão.

Pista
O nome do programa conta como argumento.
Mais uma pista
O operador < e o seu destino são processados pela shell.
Solução
argc vale 2 e argv[1] é a string 7. A shell abre dados.txt e liga-o ao descritor da entrada padrão. Nem < nem dados.txt chegam como argumentos neste comando.

Confere a tua resposta:

  • Indiquei argc = 2.
  • Indiquei argv[1] como a string 7.
  • Expliquei que stdin lê de dados.txt.

Erros frequentes

Contar o redirecionamento em argc ou abrir novamente stdin para conseguir ler os dados.
Voltar à explicação
Quem expande o padrão

A pasta tem main.c, ajuda.c e notas.txt. Compara os argumentos que os programas recebem em printf "%s " *.c e em find . -name "*.c" -print. O que muda com as aspas?

Pista
Pergunta quem vê o asterisco em cada caso.
Mais uma pista

Sem aspas, a shell substitui o padrão pelos dois nomes antes de correr.

Solução

No primeiro, a shell expande o padrão para os nomes ajuda.c e main.c, em ordem dependente da localização. printf recebe o formato e esses dois nomes como argumentos. No segundo, as aspas entregam o padrão ao find, que procura na árvore. Sem aspas, o padrão seria expandido na pasta corrente e o find receberia outros argumentos.

Confere a tua resposta:

  • Indiquei que a shell expande antes de o comando correr.
  • Distingui padrão entre aspas de padrão sem aspas.
  • Previ os argumentos recebidos pelo programa.

Erros frequentes

Achar que o programa recebe o asterisco mesmo sem aspas, ou que o glob é uma expressão regular.

Voltar à explicação
Ordem dos redirecionamentos

Compara comando > tudo.txt 2>&1 com comando 2>&1 > saida.txt. Para onde vai cada canal em cada caso?

Pista
Lê os operadores da esquerda para a direita.
Mais uma pista

2>&1 copia o destino atual de stdout nesse instante.

Solução

No primeiro, stdout passa a tudo.txt e stderr copia esse destino, por isso ambos vão para tudo.txt. No segundo, stderr copia o destino antigo de stdout, e só depois stdout muda para saida.txt, por isso stderr conserva o destino anterior. Nunca uses o ficheiro de entrada como destino antes de o programa o ler.

Confere a tua resposta:

  • Descrevi o destino de stdout em cada comando.
  • Descrevi o destino de stderr em cada comando.
  • Expliquei por que a ordem altera o resultado.

Erros frequentes

Dizer que ambas as ordens juntam os canais no mesmo ficheiro.

Voltar à explicação
Seguir campos através de três filtros

O ficheiro locais.txt contém estas quatro linhas:

porto:12:2
aveiro:5:10
porto:8:1
braga:3:3

Prevê o resultado de cut -d ':' -f 1,3 locais.txt | LC_ALL=C sort | sed 's/:/=/g'. Mostra a saída de cada filtro. O que passaria a acontecer ao ficheiro de entrada se acrescentasses > locais.txt ao fim?

Solução

cut conserva porto:2, aveiro:10, porto:1 e braga:3, nesta ordem. O campo intermédio desaparece. sort na localização C produz aveiro:10, braga:3, porto:1, porto:2. sed substitui o separador e dá:

aveiro=10
braga=3
porto=1
porto=2

Os filtros não mudam o original. Acrescentar > locais.txt cria uma disputa com a abertura de leitura da pipeline: a shell pode truncar o ficheiro antes de cut ler os dados. Não há garantia de conservar as quatro linhas. Usa outro destino e só substitui o original depois de validar o resultado.

Confere a tua resposta:

  • Selecionei apenas os campos 1 e 3.
  • Ordenei as linhas pela ordem textual indicada.
  • Substituí o separador na saída sem alterar o original.
Voltar à explicação

À tua maneira

Aparência

Modo de cor
Tema
Cor de destaque

Leitura

Fonte de leitura

Álgebra, lógica e uma ideia de cada vez.

Código

Fonte do código

Navegação

Cursor de leitura, sem edição. h, j, k, l movem; / pesquisa nesta página. v seleciona caracteres; V seleciona linhas; y copia. Tab permite destacar ou comentar. Espaço ou Enter abre blocos recolhíveis. Nos cartões, h, j, k, l mudam o foco.

CSS personalizado

Ativa uma sugestão ou guarda o teu CSS. Só muda este navegador.

Usa --page, --text e --accent para acompanhar o tema.

Seletores e recuperação

.site-header, .prose, .course-card, [data-reading-history], [data-playground] e .page-actions.

Abre a aparência com a tecla vírgula ou no rodapé. Se o CSS esconder os controlos, abre esta página sem CSS personalizado.

Pesquisar

Escreve para pesquisar em todo o site.

para escolher · Enter para abrir · Esc para fechar

Copiar fórmula

A cópia automática não está disponível. Copia o LaTeX abaixo.

Pesquisar nesta página

Enter procura · n / N repetem · Esc cancela. Ctrl / Cmd K pesquisa todo o site.

Atalhos de teclado

Clica numa tecla para a mudar. Esc cancela. Backspace desativa.

PesquisarCtrl / Cmd K

Os atalhos não interferem enquanto escreves. Tab e Enter funcionam sempre.