Ao invocar parâmetros de linha de comando via parâmetros posicionais, a ordem de entrada dos argumentos deve ser fixa, o que pode levar a erros se a sequência for incorreta. Para tornar scripts mais robustos e evitar esse problema, especialmente em funcionalidades complexas, é comum implementar suporte a opções, semelhante a ferramentas de linha de comando do Linux, onde diferentes opções e argumentos podem ser especificados.
Uso de Instrução case para Opções de Linha de Comando
Quando um script Shell precisa lidar com apenas uma opção de linha de comando, a instrução case pode ser utilizada.
$ cat gerencia_arquivo.sh
#!/bin/bash
# Script para processar arquivos com opções básicas
opcao=$1
nome_arquivo=$2
verifica_arquivo() {
if [ -z "$nome_arquivo" ]; then
echo "Nome do arquivo ausente"
exit 1
elif [ ! -f "$nome_arquivo" ]; then
echo "O arquivo $nome_arquivo não existe"
exit 2
fi
}
case "$opcao" in
-e|-E)
verifica_arquivo
echo "Editando o arquivo $nome_arquivo..."
;;
-p|-P)
verifica_arquivo
echo "Exibindo o arquivo $nome_arquivo..."
;;
*)
echo "Argumento inválido!"
echo "Uso: $(basename "$0") -e|-p nome_arquivo"
exit 3
;;
esac
Exemplo de execução:
$ ./gerencia_arquivo.sh
Argumento inválido!
Uso: gerencia_arquivo.sh -e|-p nome_arquivo
$ ./gerencia_arquivo.sh -p
Nome do arquivo ausente
$ ./gerencia_arquivo.sh -p lista.txt
Exibindo o arquivo lista.txt...
$ ./gerencia_arquivo.sh -E lista.txt
Editando o arquivo lista.txt...
Uso de getopts para Múltiplas Opções
O comando interno getopts do Bash permite analisar opções e argumentos de forma profissional. Ele oferece vantagens como não depender de programas externos, facilidade para definir variáveis Shell e conformidade com POSIX. No entanto, getopts não suporta opções longas no estilo GNU (ex.: --minha-opção) ou XF86 (ex.: -minha-opção).
Características principais:
- Reconhece opções como letras maiúsculas, minúsculas ou dígitos.
- Deve ser chamado múltiplas vezes, geralmente em um loop while, pois não altera parâmetros posicionais automaticamente.
- Interrompe a análise ao encontrar o primeiro argumento não-opção ou o delimitador duplo --.
Variáveis usadas por getopts:
OPTIND: Índice do próximo parâmetro a ser processado; reinicie para 1 antes de reutilizar.OPTARG: Argumento associado à opção encontrada.OPTERR: Controla a exibição de mensagens de erro (0 para suprimir, 1 para mostrar).
Sintaxe básica: getopts CADEIA_OPÇÕES VARIAVEL [ARGUMENTOS...], onde CADEIA_OPÇÕES define opções válidas (com : após letras para endicar argumentos obrigatórios), VARIAVEL armazena a opção atual, e ARGUMENTOS são parâmetros alternativos a serem analisados.
getopts suporta dois modos de relatório de erros: detalhado (com mensagens padrão) e suprimido (recomendado para scripts de produção).
Exemplo: Script com Opção Única
$ cat opcao_simples.sh
#!/bin/bash
# Demonstração básica de getopts
while getopts ":a" parametro; do
case "$parametro" in
a)
echo "A opção -a foi ativada!"
;;
\?)
echo "Opção inválida: -${OPTARG}"
;;
esac
done
Testes:
$ ./opcao_simples.sh
$ ./opcao_simples.sh texto.txt
$ ./opcao_simples.sh -b
Opção inválida: -b
$ ./opcao_simples.sh -a
A opção -a foi ativada!
$ ./opcao_simples.sh -a -b -c
A opção -a foi ativada!
Opção inválida: -b
Opção inválida: -c
Observações: Opções inválidas não interrompem o processamento; opções repetidas são permitidas, a menos que implemente verificação adicional.
Exemplo: Script com Múltiplas Opções
$ cat multiplo_opcoes.sh
#!/bin/bash
# Script com opções -h, -v, -f, -o
flag_verbose=off
arquivo_entrada=""
arquivo_saida=""
uso() {
echo "USO: $(basename "$0") [-h] [-v] [-f <arquivo>] [-o <arquivo>]"
exit 1
}
while getopts :hvf:o: opt; do
case "$opt" in
v) flag_verbose=on ;;
f)
arquivo_entrada="$OPTARG"
if [ ! -f "$arquivo_entrada" ]; then
echo "O arquivo de origem $arquivo_entrada não existe!"
exit 2
fi
;;
o)
arquivo_saida="$OPTARG"
if [ ! -d "$(dirname "$arquivo_saida")" ]; then
echo "O diretório de saída $(dirname "$arquivo_saida") não existe!"
exit 3
fi
;;
h) uso ;;
:)
echo "A opção -$OPTARG requer um argumento."
exit 4
;;
?)
echo "Opção inválida: -$OPTARG"
uso
exit 5
;;
esac
done
# Lógica adicional do script iria aqui
</arquivo></arquivo>
Execuções de exemplo:
$ ./multiplo_opcoes.sh -h
USO: multiplo_opcoes.sh [-h] [-v] [-f <arquivo>] [-o <arquivo>]
$ ./multiplo_opcoes.sh -vf
A opção -f requer um argumento.
$ ./multiplo_opcoes.sh -vf arquivo_inexistente.txt
O arquivo de origem arquivo_inexistente.txt não existe!
$ ./multiplo_opcoes.sh -vf arquivo.txt -o saida
</arquivo></arquivo>
Uso de getopt para Opções Longas e Flexibilidade
O comando getopt, disponível em sistemas Linux, é semelhante ao getopts, mas suporta opções longas (ex.: --opcao-longa) e oferece mais controle. Ele é um utilitário externo e requer tratamento diferente em scripts.
Sintaxe: getopt [opções] [--] cadeia-opções parâmetros, onde cadeia-opções segue o formato do getopts, e parâmetros são os argumentos a serem analisados.
Exemplo de uso básico:
$ getopt f:vl -vl -f/diretorio/arquivo param1
-v -l -f /diretorio/arquivo -- param1
getopt reorganiza os parâmetros, adicionando o delimitador -- entre opções e argumentos posicionais.
Exemplo: Reescrevendo com getopt
$ cat processa_opcoes.sh
#!/bin/bash
# Script usando getopt para analisar opções
flag_verbose=off
arquivo_entrada=""
arquivo_saida=""
uso() {
echo "USO: $(basename "$0") [-h] [-v] [-f <arquivo>] [-o <arquivo>]"
exit 1
}
# Reconfigura parâmetros posicionais com getopt
set -- $(getopt hvf:o: "$@")
while [ $# -gt 0 ]; do
case "$1" in
-v) flag_verbose=on ;;
-f)
arquivo_entrada="$2"
if [ ! -f "$arquivo_entrada" ]; then
echo "O arquivo de origem $arquivo_entrada não existe!"
exit 2
fi
shift ;;
-o)
arquivo_saida="$2"
if [ ! -d "$(dirname "$arquivo_saida")" ]; then
echo "O diretório de saída $(dirname "$arquivo_saida") não existe!"
exit 3
fi
shift ;;
-h) uso ;;
--) shift; break ;;
-*) echo "Opção inválida: $1"; uso; exit 4 ;;
*) break ;;
esac
shift
done
# Restante do script...
</arquivo></arquivo>
Testes:
$ ./processa_opcoes.sh -h
USO: processa_opcoes.sh [-h] [-v] [-f <arquivo>] [-o <arquivo>]
$ ./processa_opcoes.sh -vf arquivo.txt -o saida
</arquivo></arquivo>
Exemplo: Suporte a Opções Longas
$ cat opcoes_longas.sh
#!/bin/bash
# Script com opções curtas e longas
valor_a=""
flag_b=0
valor_c=""
# Analisa opções curtas e longas com getopt
eval set -- $(getopt -o a::bc: --long opcao-a::,opcao-b,opcao-c: -n "$(basename "$0")" -- "$@")
while true; do
case "$1" in
-a|--opcao-a)
case "$2" in
"") valor_a="valor padrão"; shift ;;
*) valor_a="$2"; shift ;;
esac ;;
-b|--opcao-b) flag_b=1 ;;
-c|--opcao-c)
case "$2" in
"") shift ;;
*) valor_c="$2"; shift; break ;;
esac ;;
--) shift; break ;;
*) echo "Erro interno!"; exit 1 ;;
esac
shift
done
echo "VALOR_A= $valor_a"
echo "FLAG_B= $flag_b"
echo "VALOR_C= $valor_c"
Exemplos de execução com opções curtas:
$ ./opcoes_longas.sh
VALOR_A=
FLAG_B= 0
VALOR_C=
$ ./opcoes_longas.sh -a -b -c 789
VALOR_A= valor padrão
FLAG_B= 1
VALOR_C= 789
$ ./opcoes_longas.sh -a123 -b -c 789
VALOR_A= 123
FLAG_B= 1
VALOR_C= 789
Exemplos com opções longas:
$ ./opcoes_longas.sh --opcao-a --opcao-b --opcao-c 789
VALOR_A= valor padrão
FLAG_B= 1
VALOR_C= 789
$ ./opcoes_longas.sh --opcao-a=123 --opcao-b --opcao-c 789
VALOR_A= 123
FLAG_B= 1
VALOR_C= 789
$ ./opcoes_longas.sh --opcao-a 456
VALOR_A= valor padrão
FLAG_B= 0
VALOR_C=
Considerações sobre opções longas: para argumentos opcionais, use = para conectar (ex.: --opcao-a=valor); para argumentos obrigatórios, pode usar espaço ou =.
Escolha entre getopts e getopt com base nas necessidades: getopts para simplicidade e compatibilidade POSIX; getopt para suporte a opções longas e maior flexibilidade em ambientes Linux.