Tutorial de Linux / Execução de comandos no Bash: operadores, aliases e variáveis
No Bash, ; executa o comando seguinte independentemente do resultado anterior, && só prossegue após sucesso e || só prossegue após um estado diferente de zero. Aliases substituem texto quando o shell lê os comandos; variáveis de ambiente levam configurações aos processos filhos. Entender a interpretação dos nomes, os estados de saída e essas conexões permite prever por que linhas parecidas se comportam de maneiras diferentes.
Comece pelas variáveis, pelo ambiente, pelos aliases e pelo fluxo básico com && e ||. Os grupos, as pipelines, as tarefas em segundo plano e o script completo aprofundam a prática quando você precisar. As aulas sobre o primeiro script Bash, em inglês e tratamento de erros no Bash, em inglês desenvolvem a organização em arquivo e os limites de falhas, caminhos e concorrência.
Como o Bash resolve o nome de um comando?
Os exemplos usam Bash. Ao ler a entrada, o shell separa palavras e operadores, expande aliases quando aplicável, interpreta a estrutura e faz as expansões e os redirecionamentos necessários antes da execução. O nome pode representar uma função, um comando interno ou um executável encontrado em PATH. Para conferir como a sessão atual interpreta um nome, execute:
type -a printf
type -a ls
command -v ls
type -a pode mostrar aliases, funções, comandos internos e candidatos executáveis, conforme o estado do shell. command -v verifica como um nome é resolvido; sua saída nem sempre é um caminho de arquivo. PATH lista os diretórios pesquisados para executáveis externos, sem explicar sozinho aliases e funções. Não substitua o PATH do sistema para fazer a prática.
Estados de saída e operadores de execução
Quando um comando termina, ele deixa um estado de saída (exit status). 0 indica sucesso; valores diferentes de zero indicam falha ou outro resultado definido pelo comando. Por exemplo, grep retorna 1 quando não encontra correspondências. Leia $? imediatamente ou salve-o em uma variável: ele representa o estado do comando concluído mais recentemente e muda quando outro comando termina.
true
printf 'status=%s\n' "$?"
false
printf 'status=%s\n' "$?"
A saída é status=0, seguida de status=1. É o estado, e não uma frase aparentemente positiva na tela, que decide a execução condicional. O Bash usa 127 quando não encontra o comando e 126 quando o encontra, mas não consegue executá-lo. A terminação por sinal segue outra convenção; nem toda falha retorna 1.
| Símbolo | Função |
|---|---|
; |
Executar o próximo comando após o anterior terminar, com sucesso ou falha |
&& |
Executar o próximo comando somente após sucesso |
|| |
Executar o próximo comando somente após um estado diferente de zero |
& |
Executar de forma assíncrona, sem esperar a conclusão |
| |
Conectar a saída padrão à entrada padrão do comando seguinte |
|& |
Enviar a saída padrão e o erro padrão pelo pipe |
! |
Inverter logicamente o estado de saída de um comando ou de uma pipeline |
A documentação de listas de comandos do Bash classifica ;, &, && e || como operadores de listas. | e |& formam pipelines; ! é uma palavra reservada que nega o estado da pipeline. Use os exemplos em Bash com true, false, printf, grep, cat e sleep, normalmente disponíveis em ambientes Ubuntu e Rocky Linux. Não é necessário acesso de administrador. Os resultados pressupõem as opções usuais do Bash; configurações como errexit podem mudar a continuação após falhas.
Conectar comandos conforme o sucesso ou a falha
Sequência com ponto e vírgula e execução condicional
; espera o comando anterior terminar e continua independentemente do resultado. Nas listas comuns, uma nova linha também separa comandos. Aspas, barras invertidas, pipes ou estruturas ainda incompletas podem fazer o Bash continuar lendo, em vez de considerar a nova linha o fim do comando.
false; printf 'always\n'
false && printf 'not run\n'
false || printf 'fallback\n'
true && printf 'next step\n'
São impressos always, fallback e next step, nessa ordem; not run não aparece. && e || fazem avaliação de curto-circuito: pulam o lado direito quando sua condição não é atendida. O padrão ilustrativo cd /caminho/real/de/trabalho && comando_de_trabalho evita executar a tarefa no diretório errado quando a mudança de diretório falha. Substitua o caminho e o comando por valores reais e preparados antes de usá-lo.
Ordem de avaliação e escolha de um ramo com if
&& e || têm a mesma precedência e se associam da esquerda para a direita. Em A && B || C, C pode ser executado mesmo se A tiver sucesso, pois B pode falhar:
true && false || printf 'fallback runs\n'
O resultado é fallback runs. Se apenas a condição original deve escolher entre dois ramos, use if:
if true; then
false
else
printf 'condition failed\n'
fi
Não há saída: a falha de false no ramo then escolhido não faz a execução passar para else. Isso não recupera a operação que falhou. Em um script real, confira as falhas das etapas e retorne o estado necessário explicitamente.
Informar uma falha e preservar seu estado
false || printf 'failure reported\n'
printf 'list status=%s\n' "$?"
A saída é failure reported, seguida de list status=0. || não significa, por si só, ignorar erros; aqui o printf bem-sucedido é o último comando executado e deixa a lista com estado zero. Se o script precisa terminar com falha após informar o problema, salve o estado original e devolva-o com exit, como no exemplo completo mais adiante.
Agrupar comandos em uma unidade
Chaves executam no shell atual
{ ...; } agrupa comandos no shell atual. Separe as chaves dos comandos com espaços e coloque ponto e vírgula ou nova linha antes da chave de fechamento. Antes destes exemplos, confirme que LESSON_SCOPE, LESSON_MODE e lesson_job não guardam valores seus; se já forem usados, escolha nomes de prática diferentes em todas as linhas correspondentes.
LESSON_SCOPE=outer
{ LESSON_SCOPE=inner; printf '%s\n' "$LESSON_SCOPE"; }
printf '%s\n' "$LESSON_SCOPE"
unset LESSON_SCOPE
inner aparece duas vezes porque a alteração continua no shell atual. O unset final remove a variável usada na prática; ele não restaura um valor anterior.
Parênteses usam um subshell
LESSON_SCOPE=outer
( LESSON_SCOPE=inner; printf '%s\n' "$LESSON_SCOPE" )
printf '%s\n' "$LESSON_SCOPE"
unset LESSON_SCOPE
São impressos inner e outer, nessa ordem. Os parênteses criam um subshell, um ambiente de execução do shell separado: mudanças em variáveis comuns e no diretório atual não permanecem no shell externo. Isso não desfaz efeitos externos, como criar ou apagar arquivos ou fazer solicitações a serviços. A documentação de agrupamento de comandos do Bash explica essa diferença.
Pipes, erro padrão e inversão do estado
Um pipe transporta dados
printf 'alpha\nbeta\n' | grep 'alpha'
A saída contém apenas alpha. | conecta a saída padrão (standard output) anterior à entrada padrão (standard input) seguinte. Ele tem outra função que ||, que seleciona a execução após um estado diferente de zero. Os comandos de uma pipeline processam fluxos conectados; não são etapas liberadas uma a uma pelo sucesso anterior. Para praticar os destinos dos dados, consulte a aula de entrada, saída e redirecionamentos no Bash.
Incluir o erro padrão com |&
bash -c 'printf "normal\n"; printf "error\n" >&2' |& cat
normal e error passam por cat. Neste exemplo, |& do Bash reúne o erro padrão (standard error) e a saída padrão, como 2>&1 |. Se houver outros redirecionamentos, a ordem importa; não substitua os operadores sem avaliar suas conexões. Um tee colocado depois pode mostrar e registrar o fluxo, mas os resultados normais e os diagnósticos estarão misturados.
! inverte o estado, sem inverter o texto
! false
printf 'inverted status=%s\n' "$?"
É impresso inverted status=0: o resultado de falha de false foi negado e passou a indicar sucesso para a condição. Um estado original zero torna-se diferente de zero. O operador não inverte mensagens de erro nem o conteúdo dos arquivos.
Conferir falhas da pipeline com pipefail
( set +o pipefail; false | cat; printf 'default=%s\n' "$?" )
( set -o pipefail; false | cat; printf 'pipefail=%s\n' "$?" )
A saída é default=0, seguida de pipefail=1. Normalmente a pipeline retorna o estado do último comando: cat pode ter sucesso e ocultar o false anterior. Com pipefail, o resultado é zero se todos tiverem sucesso; caso contrário, é o estado do comando mais à direita que terminou com estado diferente de zero. Cada comparação está em parênteses, preservando as opções do shell externo. A documentação de pipelines do Bash descreve essa regra.
Executar em segundo plano e conferir a conclusão
& inicia a execução assíncrona sem esperar a tarefa terminar. Ele difere de &&, que só prossegue após sucesso. O exemplo inicia uma espera curta e usa wait para obter o resultado da tarefa quando necessário:
sleep 2 &
lesson_job=$!
printf 'foreground continues\n'
wait "$lesson_job"
printf 'job status=%s\n' "$?"
unset lesson_job
foreground continues aparece primeiro e, depois da conclusão, aparece job status=0. $! identifica o processo da tarefa colocada mais recentemente em segundo plano. O $? logo após iniciar a tarefa não prova que ela terminou com sucesso. No Bash interativo, jobs, fg e bg permitem consultar e mover tarefas entre primeiro e segundo plano. Acrescentar & não garante que a execução continue após sair da sessão; para tarefas longas, escolha um gerenciador de sessões ou de serviços adequado.
Praticar o fluxo em um script completo
O script abaixo simula compilação, testes e implantação somente com mensagens. Ele não compila, não implanta e não apaga arquivos. Salve o conteúdo em um arquivo novo chamado course15-flow.sh, dentro de um diretório de prática vazio no qual você possa gravar. Use um editor de texto e novas linhas no formato LF. Apenas Bash é necessário; não é preciso adicionar permissão de execução, pois o arquivo será passado ao interpretador.
#!/usr/bin/env bash
build() { printf 'build\n'; }
run_tests() { printf 'test\n'; return "${1:-0}"; }
deploy() { printf 'deploy\n'; }
build && run_tests "${1:-0}" && deploy
lesson_status=$?
if (( lesson_status != 0 )); then
printf 'workflow failed: status=%s\n' "$lesson_status" >&2
fi
exit "$lesson_status"
bash course15-flow.sh 0
echo $?
bash course15-flow.sh 1
echo $?
A primeira execução imprime build, test e deploy, com estado 0. Ao mudar o argumento para 1, aparecem apenas build e test; a mensagem workflow failed: status=1 vai para o erro padrão e o script retorna 1. Execute novamente com 0 para voltar ao caminho de sucesso. ${1:-0} usa zero se o primeiro argumento não existir ou estiver vazio; nesta prática, use apenas zero ou um. O echo $? precisa vir imediatamente após a execução que você quer conferir.
Uma função definida com nome() { ...; } dá nome a um grupo de comandos; return fornece seu estado. O script salva o resultado imediatamente em lesson_status, antes de imprimir o diagnóstico, para que a mensagem não substitua a falha original. Em operações reais, use tarefas preparadas e verificadas e trate as falhas de cada etapa explicitamente.
Escolha ponto e vírgula para etapas curtas e independentes, && para tarefas que dependem de sucesso e if com funções para ramificações e recuperação. tarefa; limpeza executa a limpeza após uma falha comum, mas não garante isso se o shell terminar antes ou receber um sinal. Planeje a limpeza com recursos como trap. Também não suponha que set -e trate automaticamente todos os erros: testes de condições e listas com && ou || têm exceções. Confira explicitamente os estados importantes.
Aliases são expandidos quando o Bash lê o comando
alias cria um nome curto, usado com frequência no Bash interativo. Antes de definir ll, confira com type ll se esse nome já tem uma função ou configuração sua; nesse caso, escolha outro nome para a prática. Digite a definição abaixo e execute ll ou type ll em um novo prompt. O Bash lê e interpreta a linha antes de executá-la; definir e usar um alias na mesma linha ou no mesmo comando composto pode não produzir a expansão esperada.
alias ll='ls -l'
type ll
ll
type ll deve identificar o alias e ll deve listar o diretório com ls -l; os nomes e detalhes variam conforme os arquivos existentes. O alias vale normalmente apenas para o shell atual e, no Bash não interativo padrão, não é expandido sem ativação específica. Não faça um script depender acidentalmente de um alias interativo. Ao terminar, remova somente o alias criado para esta prática com unalias ll, ou com o nome alternativo escolhido. Para uma operação reutilizável que recebe argumentos, considere uma função do shell.
Distinguir variáveis do shell e do ambiente
Uma variável do shell pode ser usada na sessão atual. Depois de export, ela também faz parte do ambiente dos processos filhos iniciados posteriormente. Use o nome reservado para a prática, confirmado como livre, em vez de uma variável importante do sistema:
LESSON_MODE=practice
printf '%s\n' "$LESSON_MODE"
export LESSON_MODE
printenv LESSON_MODE
As duas saídas são practice. A primeira vem da expansão da variável no shell atual; a segunda é lida pelo processo externo printenv no ambiente recebido. Exportar não altera retroativamente outro shell já em execução nem o processo pai.
Para fornecer um valor somente a um comando externo, use o padrão NOME=valor comando. Ao terminar, execute unset LESSON_MODE no shell atual. Não reutilize HOME, PATH ou outros nomes importantes como variáveis de prática. Essas alterações de sessão não exigem editar arquivos de configuração.
Verificar uma ordem de execução inesperada
- Se não souber o que um nome representa, comece com
type -a nome. - Se a execução condicional surpreender, confira o estado de cada etapa separadamente.
- Se um alias não funcionar, confira se o Bash é interativo e se você o usou em uma nova linha após defini-lo.
- Se um processo filho não enxergar a variável, confira se ela foi exportada.
Operadores de sequência, aliases e variáveis influenciam a execução, mas não são intercambiáveis. Antes de conectar comandos que mudam arquivos, confirme o fluxo com comandos internos de baixo impacto, como true, false e printf.
Documentação oficial
O manual de listas de comandos do GNU Bash explica ;, && e ||. O manual de aliases do Bash explica o momento da expansão. O Bash Reference Manual detalha as variáveis e o ambiente.
As regras específicas estão nas seções oficiais sobre pipelines e pipefail, agrupamento de comandos e estados de saída.




