Condicionais e test
Esta aula aborda as estruturas condicionais em Shell Script, incluindo o uso de if/then/fi, o comando test e os colchetes simples e duplos, destacando as diferenças entre eles para escrita de scripts robustos.
Nesta aula, vamos explorar as estruturas condicionais no Shell Script, fundamentais para tomar decisões e controlar o fluxo de execução dos scripts. Começaremos com o clássico if/then/fi, passando pelo comando test e os colchetes [ ] e [[ ]], até entender as diferenças entre essas formas. Ao final, você será capaz de escrever condições complexas e saber qual sintaxe utilizar em cada contexto.
As condicionais permitem que o script execute comandos diferentes dependendo de condições como existência de arquivos, comparação de strings ou números, e saídas de comandos. O Bash oferece múltiplas maneiras de expressar essas condições, cada uma com suas particularidades.
if/then/fi
A estrutura básica de uma condicional em Shell Script é o bloco if/then/fi. A sintaxe geral é:
if comando; then
comandos_se_verdadeiro
fi
O if executa o comando especificado e verifica seu código de saída. Se o código de saída for 0 (sucesso), os comandos dentro do then são executados. Caso contrário, o script continua após o fi (que é "if" ao contrário). É possível adicionar elif e else para múltiplas condições.
Exemplo prático: verificar se um arquivo existe.
#!/bin/bash
if ls /etc/passwd > /dev/null 2>&1; then
echo "Arquivo /etc/passwd existe"
fi
Neste exemplo, o comando ls é executado; se bem-sucedido, a mensagem é exibida. Redirecionamos a saída para /dev/null para não poluir o terminal.
test e [ ]
O comando test avalia uma expressão e retorna 0 (verdadeiro) ou 1 (falso). Ele é frequentemente usado com if. A sintaxe é:
test expressão
# ou, de forma equivalente:
[ expressão ]
Os colchetes [ ] são um sinônimo do comando test, mas exigem espaços ao redor da expressão. Exemplos comuns:
test -f arquivoou[ -f arquivo ]: verdadeiro se arquivo for um arquivo regular.test "$a" = "$b"ou[ "$a" = "$b" ]: compara strings.test "$x" -gt 5ou[ "$x" -gt 5 ]: compara números (maior que).
Exemplo prático:
#!/bin/bash
diretorio="/tmp"
if [ -d "$diretorio" ]; then
echo "$diretorio é um diretório"
fi
Note que as variáveis são sempre entre aspas duplas para evitar problemas com espaços ou caracteres especiais.
[[ ]] (bash)
O Bash oferece uma versão estendida e mais segura dos colchetes: [[ ]]. Essa construção é uma palavra-chave do Bash, não um comando externo, e oferece vantagens como:
- Não requer aspas em variáveis em expressões de string (embora ainda seja boa prática usar).
- Suporta operadores adicionais:
=~para expressões regulares,&&e||dentro dos colchetes, entre outros. - Não faz expansão de palavras (word splitting) ou globbing nos operandos, o que evita erros comuns.
Sintaxe:
if [[ expressão ]]; then
comandos
fi
Exemplo com expressão regular:
#!/bin/bash
email="usuario@exemplo.com"
if [[ "$email" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
echo "Email válido"
fi
Exemplo com operadores lógicos:
#!/bin/bash
idade=25
if [[ $idade -ge 18 && $idade -le 60 ]]; then
echo "Adulto"
fi
Diferenças
As principais diferenças entre [ ] e [[ ]] são:
- Portabilidade:
[ ]é POSIX, funciona em qualquer shell (sh, bash, zsh).[[ ]]é específico do Bash (e alguns shells modernos como Zsh e Ksh). - Segurança:
[[ ]]evita problemas com variáveis vazias ou com espaços, pois não realiza word splitting. Por exemplo,[ $var = "valor" ]quebra se$varestiver vazia ou contiver espaços; já[[ $var = "valor" ]]funciona corretamente mesmo sem aspas (embora seja recomendado usar aspas). - Operadores:
[[ ]]permite&&,||,<,>(para strings, comparação lexicográfica) e=~para regex. Em[ ], os operadores lógicos devem ser-a(and) e-o(or), e a comparação de strings usa=e!=apenas. - Expressões regulares: Apenas
[[ ]]suporta o operador=~para casamento de padrões regex.
Exemplo comparativo:
#!/bin/bash
var=""
# Com [ ] isso gera erro se var estiver vazia:
if [ $var = "teste" ]; then # erro: argumento faltando
echo "igual"
fi
# Com [[ ]] funciona:
if [[ $var = "teste" ]]; then
echo "igual"
fi
Recomenda-se usar [[ ]] em scripts Bash quando a portabilidade não for uma exigência, pois é mais seguro e expressivo. Para scripts que precisam rodar em ambientes POSIX (como /bin/sh), use [ ] com cuidado com as aspas.
Boas práticas
- Sempre coloque variáveis entre aspas duplas dentro de
[ ]para evitar erros com espaços ou valores vazios. - Prefira
[[ ]]em scripts Bash para maior clareza e menos surpresas. - Use
(( ))para aritmética inteira, que é mais legível que-gt,-lt, etc. - Evite usar
-ae-odentro de[ ]; prefira usar múltiplosifou[[ ]]com&&e||.
Referências
- Bash Manual: Conditional Constructs
- POSIX test utility
- BashFAQ: What is the difference between test, [ and [[ ?
- Advanced Bash-Scripting Guide: Test Constructs
- Stack Overflow: Difference between [ and [[
- TLDP: Comparison Operators
Exercícios
-
Escreva um script que verifique se o arquivo "/etc/hosts" existe e, se existir, exiba seu conteúdo com cat.
✓ Resposta:#!/bin/bash if [ -f "/etc/hosts" ]; then cat "/etc/hosts" fi -
Escreva um script que pergunte ao usuário um número e diga se ele é maior, menor ou igual a 10. Use
[[ ]]e operadores relacionais (-gt, -lt, -eq).✓ Resposta:#!/bin/bash read -p "Digite um número: " num if [[ $num -gt 10 ]]; then echo "Maior que 10" elif [[ $num -lt 10 ]]; then echo "Menor que 10" else echo "Igual a 10" fi -
Escreva um script que receba um nome de arquivo como argumento e verifique se ele é um arquivo regular, um diretório ou não existe. Use
[ ]e operadores -f, -d.✓ Resposta:#!/bin/bash if [ $# -eq 0 ]; then echo "Uso: $0 <arquivo>" exit 1 fi arquivo="$1" if [ -f "$arquivo" ]; then echo "É um arquivo regular" elif [ -d "$arquivo" ]; then echo "É um diretório" else echo "Não existe" fi -
Escreva um script que use
[[ ]]com o operador=~para verificar se uma string fornecida pelo usuário é um número inteiro (apenas dígitos).✓ Resposta:#!/bin/bash read -p "Digite um número: " entrada if [[ "$entrada" =~ ^[0-9]+$ ]]; then echo "É um número inteiro" else echo "Não é um número inteiro" fi -
Reescreva o exercício 2 usando
[ ]e operadores-a(and) e-o(or) para combinar condições, mas sem usar elif. Dica: use múltiplos if.✓ Resposta:#!/bin/bash read -p "Digite um número: " num if [ "$num" -gt 10 ]; then echo "Maior que 10" fi if [ "$num" -lt 10 ]; then echo "Menor que 10" fi if [ "$num" -eq 10 ]; then echo "Igual a 10" fi