Validando entradas
Nesta aula, você aprenderá a validar entradas em scripts Bash, verificando argumentos, valores obrigatórios e exibindo mensagens de uso adequadas. Inclui exemplos práticos e boas práticas para tornar seus scripts mais robustos e amigáveis.
Validar entradas é uma prática essencial em scripts Bash para evitar comportamentos inesperados e garantir que o script funcione corretamente com os dados fornecidos pelo usuário. Nesta aula, abordaremos como verificar argumentos da linha de comando, garantir que valores obrigatórios sejam fornecidos e exibir mensagens de uso claras. Essas técnicas são fundamentais para criar scripts profissionais e confiáveis.
Imagine um script que precisa de um nome de arquivo como entrada. Se o usuário esquecer de passá-lo, o script pode falhar de forma confusa. Com validação adequada, podemos fornecer uma mensagem amigável e evitar erros. Vamos explorar isso em detalhes.
Verificando argumentos
Em Bash, os argumentos passados para o script são acessados por variáveis posicionais: $1, $2, etc. O número total de argumentos é armazenado em $#. Para verificar se um argumento específico foi fornecido, podemos testar se a variável correspondente está vazia ou se o número de argumentos é suficiente.
Por exemplo, se esperamos um argumento obrigatório, podemos verificar se $# é igual a zero ou menor que o esperado. Uma abordagem comum é usar uma estrutura condicional if com o operador -z para strings vazias ou comparar $# com um valor numérico.
#!/bin/bash
# Verifica se pelo menos um argumento foi passado
if [ $# -eq 0 ]; then
echo "Nenhum argumento fornecido."
exit 1
fi
echo "Primeiro argumento: $1"Além disso, podemos verificar se um argumento específico está vazio usando -z:
#!/bin/bash
if [ -z "$1" ]; then
echo "Erro: Argumento obrigatório não fornecido."
exit 1
fi
echo "Argumento: $1"Valores obrigatórios
Muitas vezes, um script exige que certos argumentos sejam fornecidos. Podemos validar isso verificando cada argumento individualmente ou usando um loop para processar opções. Para valores obrigatórios, é comum exibir uma mensagem de erro e sair do script se a condição não for atendida.
Além de verificar a existência, podemos validar o formato do valor, como se é um número, um arquivo existente, etc. Por exemplo, para garantir que o argumento seja um arquivo legível:
#!/bin/bash
if [ ! -f "$1" ]; then
echo "Erro: O arquivo '$1' não existe ou não é um arquivo regular."
exit 1
fi
echo "Arquivo válido: $1"Para múltiplos argumentos obrigatórios, podemos usar uma função de validação ou simplesmente verificar um a um:
#!/bin/bash
if [ $# -lt 2 ]; then
echo "Erro: São necessários dois argumentos."
exit 1
fi
if [ ! -f "$1" ]; then
echo "Erro: '$1' não é um arquivo."
exit 1
fi
if [ -z "$2" ]; then
echo "Erro: Segundo argumento não pode ser vazio."
exit 1
fi
echo "Argumentos válidos: $1 e $2"Mensagens de uso
Uma mensagem de uso (ou ajuda) instrui o usuário sobre como utilizar o script corretamente. Geralmente é exibida quando argumentos inválidos são fornecidos ou quando o usuário passa -h ou --help. A mensagem deve listar os argumentos esperados, opções e exemplos.
É uma boa prática definir uma função usage() que imprime a mensagem e sai do script. Essa função pode ser chamada em diferentes pontos. Exemplo:
#!/bin/bash
usage() {
echo "Uso: $0 [-o opcao] "
echo " -o opcao Opção opcional (padrão: default)"
echo " Caminho para o arquivo de entrada (obrigatório)"
exit 1
}
# Verifica se -h foi passado
if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
usage
fi
# Verifica argumento obrigatório
if [ $# -lt 1 ]; then
usage
fi
echo "Processando arquivo: $1" Mensagens de uso devem ser claras e consistentes. Inclua sempre um resumo dos argumentos e opções, além de exemplos práticos. Isso melhora a experiência do usuário e reduz erros.
Exemplos
Vamos combinar tudo em um script completo que valida argumentos, exige um arquivo e uma string, e fornece uma mensagem de uso.
#!/bin/bash
usage() {
echo "Uso: $0 [-m mensagem] "
echo " -m mensagem Mensagem a ser gravada no arquivo (opcional)"
echo " Arquivo de destino (obrigatório)"
echo "Exemplo: $0 -m 'Hello' /tmp/saida.txt"
exit 1
}
# Inicializa variáveis
mensagem=""
# Processa opções com getopts
while getopts ":m:h" opt; do
case $opt in
m)
mensagem="$OPTARG"
;;
h)
usage
;;
\?)
echo "Opção inválida: -$OPTARG" >&2
usage
;;
:)
echo "Opção -$OPTARG requer um argumento." >&2
usage
;;
esac
done
# Remove opções processadas
shift $((OPTIND-1))
# Verifica argumento posicional obrigatório
if [ $# -lt 1 ]; then
echo "Erro: Arquivo não especificado." >&2
usage
fi
arquivo="$1"
# Valida se o arquivo pode ser criado (diretório existe?)
dir=$(dirname "$arquivo")
if [ ! -d "$dir" ] && [ "$dir" != "." ]; then
echo "Erro: Diretório '$dir' não existe." >&2
exit 1
fi
# Escreve a mensagem no arquivo
if [ -n "$mensagem" ]; then
echo "$mensagem" > "$arquivo"
echo "Mensagem gravada em $arquivo"
else
echo "Nenhuma mensagem fornecida. Arquivo vazio criado: $arquivo"
touch "$arquivo"
fi Teste o script com diferentes combinações: sem argumentos, com -h, com -m, etc. Observe como as validações funcionam e como a mensagem de uso é exibida em caso de erro.
Boas práticas e observações finais
Sempre valide entradas antes de usá-las. Isso evita erros inesperados e torna o script mais seguro. Use exit 1 para indicar falha. Considere usar getopts para opções, pois ele lida com muitos casos automaticamente. Documente seu script com uma mensagem de uso clara e mantenha consistência entre scripts.
Referências
- Bash Manual: Shell Parameters
- Bash Manual: Conditional Constructs
- Bash Manual: Conditional Expressions
- Bash Manual: Getting Options (getopts)
- ShellCheck - Shell script analysis tool
Exercícios
Crie um script que exija exatamente dois argumentos: um nome de arquivo e uma string. Se o número de argumentos for diferente, exiba uma mensagem de uso.
✓ Resposta:#!/bin/bash if [ $# -ne 2 ]; then echo "Uso: $0 <arquivo> <string>" exit 1 fi echo "Arquivo: $1, String: $2"Modifique o script anterior para verificar se o primeiro argumento é um arquivo regular existente. Se não for, exiba um erro.
✓ Resposta:#!/bin/bash if [ $# -ne 2 ]; then echo "Uso: $0 <arquivo> <string>" exit 1 fi if [ ! -f "$1" ]; then echo "Erro: '$1' não é um arquivo regular." exit 1 fi echo "Arquivo: $1, String: $2"Escreva um script que aceite uma opção -n (número) e um argumento posicional (nome). O número deve ser obrigatório (opção -n) e o nome opcional. Se -n não for fornecido, exiba uso.
✓ Resposta:#!/bin/bash usage() { echo "Uso: $0 -n <número> [nome]" exit 1 } num="" while getopts ":n:" opt; do case $opt in n) num="$OPTARG" ;; \?) usage ;; :) echo "Opção -n requer um argumento." usage ;; esac done shift $((OPTIND-1)) if [ -z "$num" ]; then usage fi nome="${1:-"sem nome"}" echo "Número: $num, Nome: $nome"Crie um script que valide se o primeiro argumento é um diretório existente. Se for, liste seu conteúdo. Caso contrário, exiba erro.
✓ Resposta:#!/bin/bash if [ $# -lt 1 ]; then echo "Uso: $0 <diretório>" exit 1 fi if [ ! -d "$1" ]; then echo "Erro: '$1' não é um diretório." exit 1 fi ls -l "$1"Implemente um script que aceite dois argumentos: um arquivo de entrada e um arquivo de saída. Valide que o arquivo de entrada existe e que o diretório do arquivo de saída existe. Se alguma validação falhar, exiba mensagem apropriada.
✓ Resposta:#!/bin/bash if [ $# -ne 2 ]; then echo "Uso: $0 <entrada> <saída>" exit 1 fi if [ ! -f "$1" ]; then echo "Erro: Arquivo de entrada '$1' não existe." exit 1 fi saida_dir=$(dirname "$2") if [ ! -d "$saida_dir" ]; then echo "Erro: Diretório de saída '$saida_dir' não existe." exit 1 fi cp "$1" "$2" echo "Arquivo copiado para $2"