Operadores de comparação: numérico, string e arquivos

1. Introdução aos Operadores de Comparação

Operadores de comparação são fundamentais em scripts Bash para tomar decisões baseadas em condições. Eles permitem verificar valores numéricos, comparar strings e inspecionar propriedades de arquivos. Sem eles, scripts seriam lineares e incapazes de reagir a diferentes cenários.

A principal diferença está no tipo de dado: números são comparados com operadores específicos (-eq, -lt), enquanto strings usam operadores como = e !=. Arquivos possuem seu próprio conjunto de testes.

A estrutura básica usa [ expressão ] (comando test) ou [[ expressão ]] (palavra reservada do Bash). A versão com colchetes duplos é mais moderna, segura e flexível.

# Estrutura básica
if [ "$idade" -eq 18 ]; then
    echo "Maior de idade"
fi

# Versão com [[ ]]
if [[ "$nome" == "João" ]]; then
    echo "Olá, João"
fi

2. Comparação Numérica

Os operadores numéricos no Bash são mnemônicos e fáceis de lembrar:

Operador Significado
-eq igual
-ne diferente
-lt menor que
-le menor ou igual
-gt maior que
-ge maior ou igual
#!/bin/bash
a=10
b=20

if [ "$a" -eq "$b" ]; then
    echo "a é igual a b"
elif [ "$a" -lt "$b" ]; then
    echo "a é menor que b"
fi

# Cuidado: SEMPRE usar aspas nas variáveis
valor="5"
if [ "$valor" -gt 3 ]; then
    echo "$valor é maior que 3"
fi

Cuidados importantes: Sempre use aspas duplas nas variáveis. Se a variável estiver vazia, sem aspas o comando quebra. Além disso, números com zeros à esquerda (como 08) podem ser interpretados como octal em alguns contextos.

3. Comparação de Strings

Para strings, os operadores são diferentes:

Operador Significado
= igual (equivalente a ==)
!= diferente
< menor (ordem lexicográfica)
> maior (ordem lexicográfica)
-z string vazia (tamanho zero)
-n string não vazia
#!/bin/bash
nome="Maria"
vazia=""

if [ "$nome" = "Maria" ]; then
    echo "Nome é Maria"
fi

if [ -z "$vazia" ]; then
    echo "String vazia detectada"
fi

if [ -n "$nome" ]; then
    echo "String não vazia: $nome"
fi

# Comparação lexicográfica (com [[ ]] para evitar escaping)
if [[ "abc" < "def" ]]; then
    echo "abc vem antes de def"
fi

Diferença entre = e ==: Em Bash, ambos funcionam com [ ] e [[ ]], mas == é preferido em [[ ]] por ser mais intuitivo. O = é o padrão POSIX.

Ordenação lexicográfica: Com [ ], os operadores < e > precisam ser escapados (\< e \>). Com [[ ]], isso não é necessário.

4. Operadores de Arquivos

O Bash oferece diversos testes para arquivos e diretórios:

Existência e tipo:
| Operador | Descrição |
|----------|-------------------------------|
| -e | arquivo existe (qualquer tipo)|
| -f | é um arquivo regular |
| -d | é um diretório |
| -L | é um link simbólico |

Permissões:
| Operador | Descrição |
|----------|-------------------------------|
| -r | tem permissão de leitura |
| -w | tem permissão de escrita |
| -x | tem permissão de execução |

Propriedades:
| Operador | Descrição |
|----------|-------------------------------|
| -s | tamanho maior que zero |
| -nt | mais recente que (newer than) |
| -ot | mais antigo que (older than) |
| -ef | mesmo arquivo (hard link) |

#!/bin/bash
arquivo="/etc/passwd"

if [ -e "$arquivo" ]; then
    echo "Arquivo existe"
fi

if [ -f "$arquivo" ] && [ -r "$arquivo" ]; then
    echo "É um arquivo regular legível"
fi

if [ -d "/home" ]; then
    echo "/home é um diretório"
fi

# Comparação de timestamps
if [ "/tmp/novo.txt" -nt "/tmp/velho.txt" ]; then
    echo "novo.txt é mais recente"
fi

# Verificar link simbólico
if [ -L "/usr/bin/python" ]; then
    echo "É um link simbólico"
fi

5. Combinando Operadores com Test

Os operadores lógicos permitem criar condições complexas:

  • && (AND): ambas as condições devem ser verdadeiras
  • || (OR): pelo menos uma condição deve ser verdadeira
  • ! (NOT): inverte o resultado
#!/bin/bash
arquivo="documento.txt"

# Verificar se existe E é legível (usando [ ])
if [ -f "$arquivo" ] && [ -r "$arquivo" ]; then
    echo "Arquivo existe e é legível"
fi

# Verificar se é diretório OU link simbólico
if [ -d "$arquivo" ] || [ -L "$arquivo" ]; then
    echo "É diretório ou link"
fi

# Negação: verificar se NÃO é vazio
if [ ! -z "$variavel" ]; then
    echo "Variável não está vazia"
fi

# Combinando múltiplos testes
if [ -f "$arquivo" ] && [ -s "$arquivo" ] && [ -w "$arquivo" ]; then
    echo "Arquivo regular, não vazio e gravável"
fi

Com test explícito:

if test -f "$arquivo" && test -r "$arquivo"; then
    echo "Arquivo existe e é legível"
fi

6. Expressões com [[ ]] (Bash Avançado)

O [[ ]] é uma palavra reservada do Bash que oferece vantagens significativas:

  1. Sem necessidade de escapar operadores < e >
  2. Suporte a pattern matching com == (glob patterns)
  3. Suporte a regex com =~
  4. Operadores lógicos internos (&&, ||) sem precisar de [ ] separados
  5. Tratamento seguro de variáveis vazias
#!/bin/bash
arquivo="script.sh"

# Pattern matching (glob)
if [[ "$arquivo" == *.sh ]]; then
    echo "É um script shell"
fi

# Regex com =~
if [[ "$arquivo" =~ ^[a-z]+\.sh$ ]]; then
    echo "Nome válido de script"
fi

# Operadores combinados sem escaping
if [[ -f "$arquivo" && -x "$arquivo" ]]; then
    echo "Arquivo executável existe"
fi

# Comparação numérica com [[ ]]
if [[ "$(wc -l < "$arquivo")" -gt 10 ]]; then
    echo "Arquivo tem mais de 10 linhas"
fi

# Expressões complexas
if [[ "$1" =~ ^[0-9]+$ ]] && [[ "$1" -gt 0 && "$1" -le 100 ]]; then
    echo "Número válido entre 1 e 100"
fi

7. Erros Comuns e Boas Práticas

Erro 1: Esquecer espaços dentro dos colchetes

# ERRADO
if [$var -eq 5]; then

# CERTO
if [ "$var" -eq 5 ]; then

Erro 2: Confundir operadores numéricos com de string

# ERRADO: comparando string com operador numérico
if [ "10" -eq "10" ]; then  # funciona, mas conceitualmente errado

# CERTO para strings
if [ "$a" = "$b" ]; then

# CERTO para números
if [ "$a" -eq "$b" ]; then

Erro 3: Não usar aspas em variáveis

# ERRADO: se $nome estiver vazio, quebra
if [ $nome = "João" ]; then

# CERTO
if [ "$nome" = "João" ]; then

Boas práticas:
- Sempre use [[ ]] para scripts modernos em Bash (mais seguro e flexível)
- Use aspas duplas em todas as variáveis dentro de [ ]
- Para expressões regex, use =~ com [[ ]]
- Prefira -eq para números e = para strings
- Teste sempre arquivos com -f antes de operações de leitura/escrita

Referências