Variáveis especiais: $?, $#, $@, $0 e outras
1. Introdução às Variáveis Especiais no Bash
No Bash, variáveis especiais são símbolos pré-definidos que fornecem informações sobre o ambiente de execução do shell, argumentos de scripts, códigos de saída e processos. Diferentemente das variáveis comuns que você define (como nome="João"), as variáveis especiais são sempre acessadas com o prefixo $ e têm significados fixos atribuídos pelo próprio shell.
Elas são essenciais para criar scripts robustos, pois permitem verificar o sucesso de comandos, processar argumentos de entrada e controlar o fluxo de execução. Essas variáveis funcionam tanto em scripts quanto em funções e na linha de comando interativa.
2. $? — Código de Saída do Último Comando
O $? armazena o código de retorno (exit status) do último comando executado. Por convenção, 0 indica sucesso, enquanto qualquer valor diferente de zero (1-255) indica erro.
$ ls /etc/passwd
/etc/passwd
$ echo $?
0
$ ls /arquivo_inexistente
ls: cannot access '/arquivo_inexistente': No such file or directory
$ echo $?
2
Uso prático em condicionais:
#!/bin/bash
grep "erro" /var/log/syslog
if [ $? -eq 0 ]; then
echo "Erros encontrados no log"
else
echo "Nenhum erro encontrado"
fi
Cuidado: $? é volátil — ele muda após cada comando. Sempre capture seu valor imediatamente:
ls /tmp
resultado=$? # Salva antes de executar outro comando
echo "Comando ls retornou: $resultado"
3. $# — Número de Argumentos Passados
$# conta quantos argumentos foram passados para o script ou função. É fundamental para validação de entrada.
#!/bin/bash
# script: valida_args.sh
if [ $# -eq 0 ]; then
echo "Erro: Nenhum argumento fornecido"
echo "Uso: $0 <nome> <idade>"
exit 1
fi
echo "Número de argumentos: $#"
echo "Primeiro argumento: $1"
Execução:
$ ./valida_args.sh
Erro: Nenhum argumento fornecido
Uso: ./valida_args.sh <nome> <idade>
$ ./valida_args.sh Maria 30
Número de argumentos: 2
Primeiro argumento: Maria
Combinado com shift para processar argumentos em lote:
#!/bin/bash
while [ $# -gt 0 ]; do
echo "Processando: $1"
shift
done
4. $@ e $* — Todos os Argumentos
Ambos representam todos os argumentos passados, mas com diferença crucial no tratamento de espaços.
$* trata todos os argumentos como uma única string. $@ preserva cada argumento individual. A diferença é mais evidente com aspas duplas:
#!/bin/bash
# script: test_args.sh
echo "Usando \$*:"
for arg in $*; do
echo " -> $arg"
done
echo "Usando \"\$@\":"
for arg in "$@"; do
echo " -> $arg"
done
Execução com argumentos contendo espaços:
$ ./test_args.sh "João Silva" "Maria Santos"
Usando $*:
-> João
-> Silva
-> Maria
-> Santos
Usando "$@":
-> João Silva
-> Maria Santos
Recomendação: Sempre use "$@" para preservar a integridade dos argumentos, especialmente ao passá-los para outros comandos:
#!/bin/bash
# Correto - preserva argumentos com espaços
grep "$@" arquivo.txt
# Incorreto - quebra argumentos com espaços
grep $* arquivo.txt
5. $0 — Nome do Script ou Shell
$0 contém o caminho do script em execução ou o nome do shell interativo.
#!/bin/bash
# script: info.sh
echo "Nome do script: $0"
echo "Diretório do script: $(dirname "$0")"
echo "Nome base: $(basename "$0")"
Execução:
$ ./info.sh
Nome do script: ./info.sh
Diretório do script: .
Nome base: info.sh
$ /home/user/scripts/info.sh
Nome do script: /home/user/scripts/info.sh
Diretório do script: /home/user/scripts
Nome base: info.sh
Diferença entre $0 e $BASH_SOURCE: Em scripts sourceados (com source ou .), $0 mantém o nome do script original, enquanto $BASH_SOURCE mostra o arquivo atual.
6. $$ e $! — IDs de Processo
$$ retorna o PID (Process ID) do shell atual. $! retorna o PID do último processo executado em segundo plano com &.
#!/bin/bash
echo "PID deste script: $$"
# Criar arquivo temporário único
tempfile="/tmp/meu_script_$$.tmp"
echo "Dados temporários" > "$tempfile"
echo "Arquivo criado: $tempfile"
# Executar processo em segundo plano
sleep 30 &
pid_fundo=$!
echo "Processo em segundo plano PID: $pid_fundo"
# Aguardar e verificar
wait $pid_fundo
echo "Processo $pid_fundo finalizado"
Aplicação prática: gerar nomes de arquivos temporários únicos para evitar conflitos entre múltiplas execuções do mesmo script.
7. Outras Variáveis Especiais Relevantes
$- — Flags ativas do shell:
$ echo $-
himBHs
Cada letra representa uma opção (ex.: h para hash, B para expansão de brace).
$_ — Último argumento do comando anterior:
$ mkdir -p /tmp/pasta_teste
$ cd $_
$ pwd
/tmp/pasta_teste
$LINENO — Número da linha atual no script, útil para debug:
#!/bin/bash
echo "Estou na linha $LINENO"
if [ -f "/etc/hosts" ]; then
echo "Arquivo encontrado na linha $LINENO"
fi
$RANDOM — Gera número aleatório entre 0 e 32767:
#!/bin/bash
echo "Número aleatório: $RANDOM"
echo "Entre 1 e 10: $(( (RANDOM % 10) + 1 ))"
8. Boas Práticas e Armadilhas Comuns
Sempre usar aspas duplas em "$@", "$*" e "$0" para preservar espaços e caracteres especiais:
# Correto
cp "$@" /destino/
# Incorreto - quebra se argumentos tiverem espaços
cp $@ /destino/
Não confundir $? com saída de comando. $? é o código de retorno (número), não a saída textual. Para capturar saída, use $():
# Capturar saída (STDOUT)
saida=$(ls /tmp)
# Capturar código de retorno
ls /tmp
codigo=$?
Escopo: Variáveis especiais são locais ao shell/função atual. Dentro de uma função, $1, $#, $@ referem-se aos argumentos da função, não do script:
#!/bin/bash
minha_funcao() {
echo "Args da função: $#"
}
minha_funcao "arg1" "arg2"
echo "Args do script: $#"
Dominar essas variáveis especiais é fundamental para escrever scripts Bash profissionais, confiáveis e portáveis. Elas fornecem o controle necessário para tratamento de erros, processamento de argumentos e gerenciamento de processos que todo shell script robusto exige.
Referências
- Bash Reference Manual - Special Parameters — Documentação oficial da GNU sobre todos os parâmetros especiais do Bash, incluindo $?, $#, $@, $0 e $$.
- Advanced Bash-Scripting Guide - Internal Variables — Guia avançado com exemplos detalhados de variáveis internas e especiais do Bash.
- Bash Hackers Wiki - Special Parameters — Wiki colaborativa com explicações técnicas e exemplos práticos sobre parâmetros especiais.
- Linuxize - Bash $? Exit Status — Tutorial focado no código de saída $?, com exemplos de uso em condicionais e scripts.
- Shell Scripting Tutorial - Special Variables — Tutorial introdutório com exemplos práticos de $0, $#, $@, $* e outras variáveis especiais.