kb.erickguedes.com
Bash e Shell Script: Automação Unix/Linux

Fundamentos do Shell

Aula 1 de 6

O que é Shell?

O shell é um interpretador de comandos que fornece interface entre usuário e o sistema operacional. Os principais são:

  • bash (Bourne Again SHell) — padrão na maioria das distribuições Linux
  • zsh (Z Shell) — moderno, usado como padrão no macOS desde Catalina
  • sh (Bourne Shell) — shell original Unix, compatível POSIX
# Verificar shell atual
echo "$SHELL"

# Ver shell disponíveis
cat /etc/shells

# Mudar shell padrão
chsh -s /usr/bin/zsh

Shebang (#!)

A primeira linha de um script indica qual interpretador será usado:

#!/bin/bash
#!/usr/bin/env bash  # mais portável
#!/bin/sh
#!/usr/bin/zsh
# Exemplo de script
cat > saudacao.sh << 'EOF'
#!/bin/bash
echo "Olá, $USER!"
EOF

chmod +x saudacao.sh
./saudacao.sh

Variáveis

Locais

# Atribuição (sem espaços antes/depois do =)
nome="Maria"
idade=30

# Uso com $
echo "$nome"
echo "${nome} é uma variável local"

# Variável readonly
readonly PI=3.14159

Environment Variables

# Exportar variável
export APP_ENV="production"
export DB_URL="postgres://localhost:5432/mydb"

# Variáveis de ambiente comuns
echo "$HOME"   # /home/user
echo "$USER"   # maria
echo "$PWD"    # /home/project
echo "$PATH"   # diretórios de binários

Positional Parameters

cat > params.sh << 'EOF'
#!/bin/bash
echo "Script: $0"
echo "Primeiro argumento: $1"
echo "Segundo argumento: $2"
echo "Todos argumentos: $@"
echo "Número de argumentos: $#"
echo "Último exit code: $?"
echo "PID atual: $$"
EOF

./params.sh foo bar baz
# Script: ./params.sh
# Primeiro argumento: foo
# Todos argumentos: foo bar baz
# Número de argumentos: 3

Expansão

Brace Expansion

# Gerar sequências
echo {A,B,C}         # A B C
echo {1..5}          # 1 2 3 4 5
echo {1..10..2}      # 1 3 5 7 9
echo {a..z}          # a b c ... z

# Criar múltiplos arquivos
touch arquivo-{a,b,c}.txt
mkdir -p projeto/{src,dist,test}/{js,css}

Tilde Expansion

echo ~          # /home/user
echo ~root      # /root
echo ~other     # /home/other
echo ~+         # $PWD
echo ~-         # $OLDPWD

Parameter Expansion

nome="Maria Silva"

echo "${#nome}"            # comprimento: 11
echo "${nome:0:5}"         # substring: Maria
echo "${nome/Silva/Santos}" # substituição
echo "${nome,,}"           # minúsculas: maria silva
echo "${nome^^}"           # maiúsculas: MARIA SILVA

# Valores padrão
echo "${VAR:-padrao}"      # usa "padrao" se VAR não setada
echo "${VAR:=padrao}"      # seta VAR com "padrao" e usa
echo "${VAR:?erro}"        # erro se VAR não setada

Command Substitution

# Sintaxe moderna $()
data_atual=$(date +%Y-%m-%d)
arquivos=$(ls -la | wc -l)

# Sintaxe antiga (evitar)
data_atual=`date +%Y-%m-%d`

# Aninhamento
dir_atual=$(basename "$(pwd)")

Quoting

# Aspas simples — literais (sem expansão)
echo 'O $HOME é $USER'     # O $HOME é $USER

# Aspas duplas — permite expansão
echo "O $HOME é $USER"     # O /home/maria é maria

# Escape
echo "Preço: \$100"        # Preço: $100
echo "Arquivo: \"teste\""  # Arquivo: "teste"

Exit Codes

# 0 = sucesso, 1-255 = erro
ls /tmp
echo $?   # 0

ls /naoexiste
echo $?   # 2

# Convenções comuns
# 0  → sucesso
# 1  → erro genérico
# 2  → uso incorreto
# 127 → comando não encontrado

# Usar em script
if cd "$diretorio"; then
    echo "Diretório acessado"
fi

$PATH

# Diretórios onde o shell procura executáveis
echo "$PATH"
# /usr/local/bin:/usr/bin:/bin:/usr/local/games

# Adicionar diretório ao PATH
export PATH="$HOME/bin:$PATH"

# type vs which
type python      # mostra como o shell interpreta
type -a python   # todas as ocorrências
which python     # caminho do executável

Lab: Script de Boas-Vindas com Validação

Crie um script interativo que utiliza os fundamentos aprendidos.

cat > boas-vindas.sh << 'SCRIPT'
#!/bin/bash

# Modo estrito
set -euo pipefail

# Constantes
readonly NOME_SCRIPT=$(basename "$0")

# Função de uso
uso() {
    echo "Uso: $NOME_SCRIPT [--nome NOME] [--idade IDADE]"
    echo "Exemplo: $NOME_SCRIPT --nome Maria --idade 30"
    exit 1
}

# Parse básico de argumentos
NOME="${1:-Mundo}"
IDADE=""

while [[ $# -gt 0 ]]; do
    case "$1" in
        --nome) NOME="$2"; shift 2 ;;
        --idade) IDADE="$2"; shift 2 ;;
        *) uso ;;
    esac
done

# Validações
[[ -z "$NOME" ]] && { echo "Erro: Nome não pode ser vazio"; exit 1; }
[[ "$IDADE" =~ ^[0-9]+$ ]] || { echo "Idade deve ser numérica"; exit 1; }

# Saudação com expansão
echo "Olá, ${NOME}!"
echo "Idade: ${IDADE:-não informada}"
echo "Executado por: ${USER}"
echo "Diretório: ${PWD}"
echo "Timestamp: $(date '+%Y-%m-%d %H:%M:%S')"
echo "Exit code: $?"
SCRIPT

chmod +x boas-vindas.sh

# Testar
./boas-vindas.sh --nome "João" --idade 28
echo "Exit do script: $?"

Shebang define o interpretador. Expansão e quoting controlam como o shell processa variáveis e comandos. Exit codes são a base para controle de fluxo e tratamento de erros.