Controle de Fluxo e Funções
Aula 2 de 6
Condicionais: if / test / [[
test e [ ]
# Sintaxe: test <expressão> ou [ <expressão> ]
# Testes de arquivo
test -f "arquivo.txt" && echo "É arquivo regular"
[ -d "diretorio" ] && echo "É diretório"
[ -e "caminho" ] && echo "Existe"
[ -r "arquivo" ] && echo "Legível"
[ -w "arquivo" ] && echo "Gravável"
[ -x "script.sh" ] && echo "Executável"
[ -s "arquivo" ] && echo "Tamanho > 0"
[ -L "link" ] && echo "É symlink"
[[ ]] — Versão Moderna
# [[ ]] é mais seguro e poderoso que [ ]
# Strings
[[ "$nome" == "Maria" ]] && echo "Igual"
[[ "$nome" != "João" ]] && echo "Diferente"
[[ -z "$vazia" ]] && echo "String vazia"
[[ -n "$nome" ]] && echo "String não vazia"
[[ "hello" == h* ]] && echo "Glob match"
# Numérico (com -eq, -ne, -lt, -le, -gt, -ge)
[[ $idade -ge 18 ]] && echo "Maior de idade"
[[ $qtde -gt 0 ]] && echo "Maior que zero"
# Operadores lógicos
[[ -f "$file" && -r "$file" ]] && echo "Arquivo legível"
[[ "$user" == "root" || $UID -eq 0 ]] && echo "Acesso root"
# Regex (operador =~)
[[ "$email" =~ ^[a-z]+@[a-z]+\.[a-z]{2,}$ ]] && echo "Email válido"
if / elif / else
if [[ $# -eq 0 ]]; then
echo "Nenhum argumento"
elif [[ $# -eq 1 ]]; then
echo "Um argumento: $1"
else
echo "Múltiplos argumentos: $@"
fi
case
case "$1" in
start)
echo "Iniciando serviço..."
;;
stop)
echo "Parando serviço..."
;;
restart|reload)
echo "Reiniciando..."
;;
[0-9][0-9])
echo "Número de dois dígitos: $1"
;;
*.txt)
echo "Arquivo de texto: $1"
;;
"")
echo "Argumento vazio"
;;
*)
echo "Opção desconhecida: $1"
exit 1
;;
esac
Fallthrough (;&)
# ;& permite continuar para o próximo padrão
case "$nivel" in
alto)
echo "Nível alto"
;&
medio)
echo "Nível médio"
;&
baixo)
echo "Nível baixo"
;;
esac
Loops
for — C-style
# Sintaxe clássica C
for ((i = 0; i < 10; i++)); do
echo "Iteração $i"
done
# Decremento
for ((i = 10; i > 0; i--)); do
echo "Contagem regressiva: $i"
done
# Passo diferente
for ((i = 0; i <= 100; i += 10)); do
echo "$i%"
done
for — for-in
# Lista explícita
for cor in vermelho azul verde; do
echo "Cor: $cor"
done
# Globbing
for file in *.txt; do
echo "Processando: $file"
done
# Sequência com seq
for i in $(seq 1 5); do
echo "$i"
done
# Brace expansion
for i in {1..10}; do
square=$((i * i))
echo "$i² = $square"
done
# Array
frutas=("maçã" "banana" "laranja")
for fruta in "${frutas[@]}"; do
echo "Fruta: $fruta"
done
while
# Loop com contador
count=0
while [[ $count -lt 5 ]]; do
echo "Contagem: $count"
((count++))
done
# Ler arquivo linha a linha
while IFS= read -r linha; do
echo "Linha: $linha"
done < "arquivo.txt"
# Loop infinito (com break)
while true; do
read -p "Comando: " cmd
[[ "$cmd" == "sair" ]] && break
echo "Executando: $cmd"
done
until
# Executa ENQUANTO condição é falsa
contador=0
until [[ $contador -ge 5 ]]; do
echo "Contagem: $contador"
((contador++))
done
# 0, 1, 2, 3, 4
break e continue
for i in {1..10}; do
[[ $i -eq 3 ]] && continue # pula o 3
[[ $i -eq 8 ]] && break # para no 8
echo "$i"
done
# 1 2 4 5 6 7
Funções
Definição
# Sintaxe 1 (recomendada)
minha_funcao() {
local name="$1"
echo "Olá, $name!"
}
# Sintaxe 2 (function explícito)
function minha_funcao {
echo "Olá!"
}
Argumentos e Local
calculadora() {
local a="$1"
local op="$2"
local b="$3"
case "$op" in
+) echo $((a + b)) ;;
-) echo $((a - b)) ;;
\*) echo $((a * b)) ;;
/) echo $((a / b)) ;;
*) echo "Operador inválido"; return 1 ;;
esac
}
# Chamar
resultado=$(calculadora 10 + 5)
echo "Resultado: $resultado"
return vs echo
# return: código de saída (0-255)
is_even() {
local num=$1
return $((num % 2))
}
is_even 4 && echo "Par" # Par
is_even 3 || echo "Ímpar" # Ímpar
# echo: retornar valor
get_username() {
echo "$USER"
}
nome=$(get_username)
echo "Usuário: $nome"
source
# Arquivo lib.sh
cat > lib.sh << 'EOF'
log_info() { echo "[INFO] $*"; }
log_error() { echo "[ERROR] $*" >&2; }
EOF
# Script principal
cat > main.sh << 'EOF'
#!/bin/bash
source ./lib.sh # ou . ./lib.sh
log_info "Script iniciado"
log_error "Algo deu errado"
EOF
Lab: Gerenciador de Tarefas via CLI
cat > task-manager.sh << 'SCRIPT'
#!/bin/bash
set -euo pipefail
TASKS_FILE="${HOME}/.tasks.txt"
tarefa_listar() {
if [[ ! -f "$TASKS_FILE" ]]; then
echo "Nenhuma tarefa encontrada."
return
fi
local count=0
while IFS= read -r task; do
((count++))
echo "[$count] $task"
done < "$TASKS_FILE"
}
tarefa_adicionar() {
echo "$*" >> "$TASKS_FILE"
echo "Tarefa adicionada: $*"
}
tarefa_remover() {
local num="$1"
local tmp=$(mktemp)
local count=0
while IFS= read -r task; do
((count++))
[[ $count -eq $num ]] && continue
echo "$task" >> "$tmp"
done < "$TASKS_FILE"
mv "$tmp" "$TASKS_FILE"
echo "Tarefa $num removida."
}
case "${1:-}" in
list)
tarefa_listar
;;
add)
shift
tarefa_adicionar "$*"
;;
rm)
tarefa_remover "$2"
;;
*)
echo "Uso: $0 {list|add <texto>|rm <num>}"
exit 1
;;
esac
SCRIPT
chmod +x task-manager.sh
# Testar
./task-manager.sh add "Estudar bash"
./task-manager.sh add "Fazer exercícios"
./task-manager.sh list
./task-manager.sh rm 1
[[ ]] é mais seguro que [ ] — permite regex, glob e operadores lógicos. Use local em funções para isolar variáveis. return é para exit code, echo para valores.