if / elif / else

A estrutura básica de decisão no Bash. O if avalia o código de saída de um comando — 0 é verdadeiro, qualquer outra coisa é falso.

#!/bin/bash
ESPACO=$(df / --output=pcent | tail -1 | tr -d ' %')

if [[ $ESPACO -ge 90 ]]; then
  echo "CRITICO: disco em ${ESPACO}%"
elif [[ $ESPACO -ge 70 ]]; then
  echo "ALERTA: disco em ${ESPACO}%"
else
  echo "OK: disco em ${ESPACO}%"
fi
OK: disco em 42%

test e [ ]

O comando test e sua forma abreviada [ ] são equivalentes. Preferível usar [[ ]] no Bash, pois é mais seguro e flexível.

# Estas três formas são equivalentes:
test -f /etc/hostname   && echo "existe"
[ -f /etc/hostname ]    && echo "existe"
[[ -f /etc/hostname ]]  && echo "existe"

Testes com arquivos

Operadores para verificar propriedades de arquivos e diretórios:

CONF="/etc/ssh/sshd_config"

[[ -f "$CONF" ]] && echo "arquivo regular existe"
[[ -d /var/log ]] && echo "diretório existe"
[[ -r "$CONF" ]] && echo "tem permissão de leitura"
[[ -w "$CONF" ]] && echo "tem permissão de escrita"
[[ -x /usr/bin/bash ]] && echo "é executável"
[[ -s "$CONF" ]] && echo "arquivo não está vazio"
[[ -L /usr/bin/python ]] && echo "é link simbólico"

Testes com strings

Os operadores -z e -n verificam se uma string está vazia ou não:

HOSTNAME=$(hostname)

[[ -z "$HOSTNAME" ]] && echo "hostname vazio!"
[[ -n "$HOSTNAME" ]] && echo "hostname: $HOSTNAME"

# Comparação de strings
[[ "$USER" == "root" ]] && echo "Você é root"
[[ "$USER" != "root" ]] && echo "Você não é root"

# Pattern matching (só funciona com [[ ]])
[[ "$HOSTNAME" == srv-* ]] && echo "Este é um servidor"

Comparações numéricas

Dentro de [[ ]] use os operadores tradicionais. Dentro de (( )) use sinais matemáticos.

PROCS=$(ps aux | wc -l)

# Com [[ ]] — operadores textuais
[[ $PROCS -gt 200 ]] && echo "Muitos processos: $PROCS"
[[ $PROCS -lt 50 ]]  && echo "Poucos processos: $PROCS"
[[ $PROCS -eq 100 ]] && echo "Exatamente 100"

# Com (( )) — operadores matemáticos
(( PROCS > 200 )) && echo "Muitos processos"
(( PROCS >= 100 && PROCS <= 300 )) && echo "Faixa normal"
Dica: Os operadores numéricos dentro de [[ ]] são: -eq (igual), -ne (diferente), -lt (menor), -le (menor ou igual), -gt (maior), -ge (maior ou igual).

case / esac

Ideal para múltiplas comparações de padrão. Muito usado em scripts de inicialização e menus.

#!/bin/bash
case "$1" in
  start)
    echo "Iniciando serviço..."
    ;;
  stop)
    echo "Parando serviço..."
    ;;
  restart|reload)
    echo "Reiniciando serviço..."
    ;;
  status)
    echo "Serviço ativo"
    ;;
  *)
    echo "Uso: $0 {start|stop|restart|status}"
    exit 1
    ;;
esac
$ ./servico.sh restart
Reiniciando serviço...

O case suporta globs. Um exemplo que detecta o tipo de arquivo pela extensão:

ARQUIVO="backup.tar.gz"

case "$ARQUIVO" in
  *.tar.gz|*.tgz)  echo "Arquivo tar comprimido com gzip" ;;
  *.tar.bz2)       echo "Arquivo tar comprimido com bzip2" ;;
  *.zip)           echo "Arquivo ZIP" ;;
  *.log)           echo "Arquivo de log" ;;
  *)               echo "Tipo desconhecido" ;;
esac
Dica: Use ;;& em vez de ;; para continuar testando os próximos padrões (fall-through). Disponível a partir do Bash 4.0.