O que é o comando dois-pontos no Bash

O : (dois-pontos) e um comando embutido do Bash e de praticamente todos os shells POSIX. Ele não faz absolutamente nada, mas retorna sucesso (exit code 0) sempre. Por isso é chamado de comando nulo ou null command.

Um artigo técnico recente viralizou no Hacker News com o titulo 'A shell cólon does nothing. Use it anyway', com mais de 160 pontos e quase 60 comentários. O motivo e que, apesar de parecer inútil, o : tem casos de uso práticos e bem estabelecidos em scripts shell de produção.

Se você já viu um script com `: ${VARIÁVEL:=valor}` ou um loop infinito com `while :; do`, agora vai entender o que aquilo significa e por que foi escrito assim.

Como funciona

Internamente, o : e um builtin do shell, o que significa que não existe como um arquivo executável em /usr/bin ou /bin. Ele é executado diretamente pelo interpretador do shell, sem fork de processo.

O comportamento e simples: o shell avalia todos os argumentos passados para o : (o que dispara substituições de variáveis e expansões), e então descarta tudo e retorna exit code 0. Isso e o que o diferencia de um simples comentário (#): os argumentos são realmente avaliados.

Essa avaliação dos argumentos e exatamente o que torna o : útil em certos contextos, especialmente quando você quer aproveitar efeitos colaterais de expansões de parâmetro sem executar nenhum comando de verdade.

Principais usos práticos

Os usos mais comuns do : em scripts reais são:

  • Valores padrão para variáveis: : ${PORTA:=8080} define PORTA como 8080 se ela ainda não tiver valor, sem precisar de um if.
  • Loop infinito legível: while :; do ... done e equivalente a while true; do ... done, mas sem depender de /usr/bin/true existir.
  • Placeholder em blocos condicionais: quando um bloco then ou else precisa existir mas não deve fazer nada, o : serve como corpo vazio valido.
  • Verificar se variável esta definida: : ${VARIÁVEL:?'erro: variável não definida'} aborta o script com mensagem se VARIÁVEL estiver vazia.
  • Comentários de documentação executáveis: alguns scripts usam `: 'texto de documentação aqui'` para incluir notas que ficam no código sem virar comentários ocultos.
💡
Dica

Use : ${VAR:=padrão} no inicio de scripts para definir valores padrão de todas as variáveis de configuração em um bloco só, sem precisar de vários if-then-fi.

Como começar: reconhecendo e usando no dia a dia

Você provavelmente já encontrou o : em scripts e não sabia o que era. O primeiro passo e reconhecer os padrões mais comuns.

Para testar no terminal: abra um shell Bash e execute apenas `:` seguido de Enter. Nada acontece visualmente, e isso é o esperado. Execute `echo $?` logo depois e vera o valor 0 (sucesso).

Para o caso de valor padrão, teste com: `: ${PORTA:=8080}` e depois `echo $PORTA`. Você vai ver 8080 aparecer, sem nenhum if, sem subshell, em uma linha só.

# teste no terminal
:
echo $?  # saída: 0

# valor padrão de variável
: ${PORTA:=8080}
echo $PORTA  # saída: 8080

# loop infinito
while :; do echo tick; sleep 1; done

Exemplo prático: script de deploy com defaults

Imagine um script de deploy que pode receber configurações via variáveis de ambiente, mas tem valores padrão sensíveis para quando nenhum e passado. Com o :, isso fica limpo e legível.

Em vez de varias estruturas if-then-fi, você escreve um bloco de defaults no topo do script usando : com o operador := para cada variável. Qualquer variável que já tenha valor permanece intacta; as que estiverem vazias recebem o padrão definido ali.

Isso e especialmente útil em imagens Docker e pipelines de CI/CD onde variáveis de ambiente são passadas de fora e precisam de fallback seguro.

#!/bin/bash
# Defaults do deploy
: ${AMBIENTE:=staging}
: ${PORTA:=8080}
: ${TIMEOUT:=30}
: ${REPOSITÓRIO:=meu-app}

echo "Deploy de $REPOSITÓRIO em $AMBIENTE na porta $PORTA"

Comparação com alternativas

Para valores padrão, a alternativa mais comum e o if-then-fi clássico. Funciona, mas e mais verboso. Outra opcao e a expansão de parâmetro inline: `${VAR:-padrão}` retorna o padrão se VAR estiver vazia, mas sem atribuir o valor a variável de fato.

O : com := e único porque atribui o valor padrão a variável, não só o usa momentaneamente. Após a execução de `: ${VAR:=padrão}`, a variável VAR realmente tem o valor 'padrão' para o resto do script.

Para loops infinitos, `while true` depende do executável /usr/bin/true existir no sistema (quase universal, mas tecnicamente uma dependência externa). O `while :` usa apenas o builtin do shell e funciona mesmo em ambientes minimalistas como algumas imagens Docker base.

Pontos positivos e limitações

A principal vantagem do : e a portabilidade. Por ser um builtin POSIX, funciona em qualquer shell compatível: Bash, sh, dash, zsh, ash. Em ambientes minimalistas de containers ou sistemas embarcados onde /usr/bin/true pode não existir, o : e mais robusto.

Outra vantagem e a eficiência marginal: sem fork de processo, o : e ligeiramente mais rápido que chamar um executável externo em loops muito apertados. Na prática, essa diferença raramente importa, mas e um argumento técnico valido.

A limitação principal e a legibilidade para quem não conhece o idioma. Um time que nunca viu `: ${VAR:=x}` vai precisar de comentário explicando o que aquilo faz. Em codebases colaborativas, pese o ganho técnico contra o custo de explicação.

⚠️
Atenção

O : avalia os argumentos mesmo não fazendo nada com eles. Isso significa que `: $(rm -rf /)` executaria o rm. Nunca use : com substituição de comandos de origem desconhecida.

Casos de uso reais

Scripts de inicialização de containers Docker: entrypoints que aceitam configuração via env vars usam : para definir defaults de forma compacta e portável.

Pipelines de CI/CD: scripts de build que precisam funcionar em diferentes ambientes (dev, staging, produção) com configurações diferentes mas valores padrão sensíveis.

Scripts de configuração de servidores: playbooks shell que configuram ambientes novos e precisam de valores padrão para portas, caminhos e flags opcionais.

Blocos condicionais vazios em scripts POSIX: quando uma condição tem tratamento apenas em um dos ramos, o : preenche o ramo vazio de forma sintaticamente correta.

Dicas e boas práticas

💡
Dica

Agrupe todos os : de defaults no topo do script, logo após o shebang e antes de qualquer lógica. Isso cria uma secao de configuração clara e fácil de encontrar.

💡
Dica

Para verificar variáveis obrigatórias, use `: ${VAR:?'Erro: VAR não definida'}`. Se VAR estiver vazia, o script aborta imediatamente com a mensagem de erro que você escreveu.

🚀
Pro tip

Em scripts que precisam ser POSIX-compatibles (não apenas Bash), prefira : a true e while : a while true. Garante que o script funcione no dash (que muitas distros usam como /bin/sh) sem modificações.

🔴
Cuidado

Não confunda : (dois-pontos, comando nulo) com ; (ponto-e-virgula, separador de comandos) ou com : usado em caminhos de variáveis PATH. São usos totalmente diferentes do mesmo caractere em contextos diferentes.

Vale a pena aprender?

Para quem escreve scripts shell ocasionalmente, o : e um curiosidade interessante mas não essencial. Você pode fazer tudo sem ele usando if-then-fi e while true.

Para quem escreve scripts de produção, especialmente para ambientes Docker, CI/CD ou sistemas POSIX variados, entender o : e os operadores de expansão de parâmetro do shell e parte do repertório básico. Deixa o código mais compacto e mais portável.

O próximo passo: abra um script shell que você manteve recentemente e veja quantos if-then-fi poderiam virar uma linha com : e os operadores de parâmetro. Você provavelmente vai encontrar pelo menos um.