Aprende a crear scripts profesionales que manejen argumentos de forma robusta y flexible
Los argumentos de línea de comandos son fundamentales para crear scripts flexibles y reutilizables. En este módulo aprenderás a manejar parámetros de forma profesional, crear interfaces de usuario intuitivas y validar entradas de manera robusta.
En Bash, los argumentos se pasan al script y se almacenan en variables especiales:
Variable | Descripción | Ejemplo |
---|---|---|
$0 |
Nombre del script | script.sh |
$1, $2, ..., $n |
Argumentos posicionales | primer, segundo argumento |
$# |
Número total de argumentos | 3 |
$* |
Todos los argumentos como cadena | "arg1 arg2 arg3" |
$@ |
Todos los argumentos como array | ["arg1", "arg2", "arg3"] |
$$ |
PID del proceso actual | 1234 |
$? |
Código de salida del último comando | 0 (éxito) o >0 (error) |
#!/bin/bash
# Script básico para mostrar argumentos
echo "Nombre del script: $0"
echo "Primer argumento: $1"
echo "Segundo argumento: $2"
echo "Tercer argumento: $3"
echo ""
echo "Número total de argumentos: $#"
echo "Todos los argumentos (\$*): $*"
echo "Todos los argumentos (\$@): $@"
echo "PID del proceso: $$"
chmod +x argumentos.sh
./argumentos.sh archivo.txt backup 2024
#!/bin/bash
# Script de backup con validación de argumentos
# Función para mostrar ayuda
mostrar_ayuda() {
echo "Uso: $0 [OPCIONES] DIRECTORIO_ORIGEN DIRECTORIO_DESTINO"
echo ""
echo "OPCIONES:"
echo " -h, --help Mostrar esta ayuda"
echo " -v, --verbose Modo verbose"
echo " -c, --compress Comprimir backup"
echo " -t, --timestamp Agregar timestamp al nombre"
echo ""
echo "Ejemplos:"
echo " $0 /home/usuario /backup"
echo " $0 -v -c /documentos /backup"
echo " $0 --verbose --timestamp /proyecto /backup"
exit 0
}
# Verificar número mínimo de argumentos
if [ $# -lt 2 ]; then
echo "Error: Se requieren al menos 2 argumentos"
echo "Use '$0 --help' para ver la ayuda"
exit 1
fi
# Variables por defecto
VERBOSE=false
COMPRESS=false
TIMESTAMP=false
ORIGEN=""
DESTINO=""
# Procesar argumentos
while [ $# -gt 0 ]; do
case $1 in
-h|--help)
mostrar_ayuda
;;
-v|--verbose)
VERBOSE=true
shift
;;
-c|--compress)
COMPRESS=true
shift
;;
-t|--timestamp)
TIMESTAMP=true
shift
;;
-*)
echo "Error: Opción desconocida $1"
echo "Use '$0 --help' para ver opciones válidas"
exit 1
;;
*)
# Argumentos posicionales
if [ -z "$ORIGEN" ]; then
ORIGEN="$1"
elif [ -z "$DESTINO" ]; then
DESTINO="$1"
else
echo "Error: Demasiados argumentos"
exit 1
fi
shift
;;
esac
done
# Validar que se proporcionaron origen y destino
if [ -z "$ORIGEN" ] || [ -z "$DESTINO" ]; then
echo "Error: Debe especificar directorio origen y destino"
exit 1
fi
# Validar que el directorio origen existe
if [ ! -d "$ORIGEN" ]; then
echo "Error: El directorio origen '$ORIGEN' no existe"
exit 1
fi
# Crear directorio destino si no existe
if [ ! -d "$DESTINO" ]; then
mkdir -p "$DESTINO"
[ $VERBOSE = true ] && echo "Directorio destino creado: $DESTINO"
fi
# Generar nombre de backup
BACKUP_NAME="backup"
if [ $TIMESTAMP = true ]; then
BACKUP_NAME="${BACKUP_NAME}_$(date +%Y%m%d_%H%M%S)"
fi
# Mostrar configuración si verbose está activado
if [ $VERBOSE = true ]; then
echo "=== CONFIGURACIÓN DE BACKUP ==="
echo "Origen: $ORIGEN"
echo "Destino: $DESTINO"
echo "Nombre: $BACKUP_NAME"
echo "Comprimir: $COMPRESS"
echo "Timestamp: $TIMESTAMP"
echo "================================"
fi
# Realizar backup
if [ $COMPRESS = true ]; then
tar -czf "$DESTINO/$BACKUP_NAME.tar.gz" -C "$(dirname "$ORIGEN")" "$(basename "$ORIGEN")"
[ $VERBOSE = true ] && echo "Backup comprimido creado: $DESTINO/$BACKUP_NAME.tar.gz"
else
cp -r "$ORIGEN" "$DESTINO/$BACKUP_NAME"
[ $VERBOSE = true ] && echo "Backup creado: $DESTINO/$BACKUP_NAME"
fi
echo "Backup completado exitosamente"
El comando shift
permite desplazar los argumentos posicionales hacia la izquierda, útil para procesar argumentos de longitud variable:
#!/bin/bash
# Script que procesa múltiples archivos
echo "Procesando archivos..."
# Contar archivos iniciales
echo "Total de archivos: $#"
# Procesar cada archivo
contador=1
while [ $# -gt 0 ]; do
echo "[$contador] Procesando: $1"
# Aquí iría la lógica de procesamiento
if [ -f "$1" ]; then
echo " ✓ Archivo válido"
wc -l "$1" 2>/dev/null && echo " ✓ Líneas contadas"
else
echo " ✗ Archivo no encontrado"
fi
# Desplazar argumentos
shift
((contador++))
done
echo "Procesamiento completado"
#!/bin/bash
# Script de configuración con argumentos que requieren valores
# Variables por defecto
HOST=""
PORT=22
USER=""
PASSWORD=""
TIMEOUT=30
# Función de ayuda
mostrar_uso() {
cat << EOF
Uso: $0 [OPCIONES]
OPCIONES:
-h, --host HOST Servidor host (requerido)
-p, --port PORT Puerto (default: 22)
-u, --user USER Usuario (requerido)
-w, --password PASS Contraseña
-t, --timeout SECS Timeout en segundos (default: 30)
--help Mostrar esta ayuda
Ejemplo:
$0 -h servidor.com -u admin -p 2222 -t 60
EOF
}
# Procesar argumentos
while [ $# -gt 0 ]; do
case $1 in
-h|--host)
if [ -n "$2" ] && [ "${2:0:1}" != "-" ]; then
HOST="$2"
shift 2
else
echo "Error: --host requiere un valor"
exit 1
fi
;;
-p|--port)
if [ -n "$2" ] && [ "${2:0:1}" != "-" ]; then
PORT="$2"
shift 2
else
echo "Error: --port requiere un valor"
exit 1
fi
;;
-u|--user)
if [ -n "$2" ] && [ "${2:0:1}" != "-" ]; then
USER="$2"
shift 2
else
echo "Error: --user requiere un valor"
exit 1
fi
;;
-w|--password)
if [ -n "$2" ] && [ "${2:0:1}" != "-" ]; then
PASSWORD="$2"
shift 2
else
echo "Error: --password requiere un valor"
exit 1
fi
;;
-t|--timeout)
if [ -n "$2" ] && [ "${2:0:1}" != "-" ] && [[ "$2" =~ ^[0-9]+$ ]]; then
TIMEOUT="$2"
shift 2
else
echo "Error: --timeout requiere un número válido"
exit 1
fi
;;
--help)
mostrar_uso
exit 0
;;
*)
echo "Error: Opción desconocida '$1'"
mostrar_uso
exit 1
;;
esac
done
# Validar argumentos requeridos
if [ -z "$HOST" ]; then
echo "Error: Se requiere especificar --host"
exit 1
fi
if [ -z "$USER" ]; then
echo "Error: Se requiere especificar --user"
exit 1
fi
# Mostrar configuración
echo "=== CONFIGURACIÓN ==="
echo "Host: $HOST"
echo "Port: $PORT"
echo "User: $USER"
echo "Password: ${PASSWORD:+***configurada***}"
echo "Timeout: $TIMEOUT segundos"
echo "===================="
# Aquí iría la lógica principal del script
echo "Conectando a $USER@$HOST:$PORT..."
echo "Configuración aplicada correctamente"
#!/bin/bash
# Funciones de validación
# Validar que sea un número entero
validar_entero() {
local valor="$1"
local nombre="$2"
if ! [[ "$valor" =~ ^-?[0-9]+$ ]]; then
echo "Error: $nombre debe ser un número entero válido"
return 1
fi
return 0
}
# Validar que sea un número entero positivo
validar_entero_positivo() {
local valor="$1"
local nombre="$2"
if ! validar_entero "$valor" "$nombre"; then
return 1
fi
if [ "$valor" -le 0 ]; then
echo "Error: $nombre debe ser mayor que 0"
return 1
fi
return 0
}
# Validar formato de email
validar_email() {
local email="$1"
local patron="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
if [[ ! "$email" =~ $patron ]]; then
echo "Error: Formato de email inválido: $email"
return 1
fi
return 0
}
# Validar que un archivo existe y es legible
validar_archivo() {
local archivo="$1"
if [ ! -f "$archivo" ]; then
echo "Error: El archivo '$archivo' no existe"
return 1
fi
if [ ! -r "$archivo" ]; then
echo "Error: No se puede leer el archivo '$archivo'"
return 1
fi
return 0
}
# Validar que un directorio existe y es escribible
validar_directorio() {
local directorio="$1"
if [ ! -d "$directorio" ]; then
echo "Error: El directorio '$directorio' no existe"
return 1
fi
if [ ! -w "$directorio" ]; then
echo "Error: No se puede escribir en el directorio '$directorio'"
return 1
fi
return 0
}
# Validar rango de puerto
validar_puerto() {
local puerto="$1"
if ! validar_entero_positivo "$puerto" "puerto"; then
return 1
fi
if [ "$puerto" -lt 1 ] || [ "$puerto" -gt 65535 ]; then
echo "Error: El puerto debe estar entre 1 y 65535"
return 1
fi
return 0
}
# Ejemplo de uso con validación
main() {
local email=""
local puerto=""
local archivo=""
local directorio=""
# Procesar argumentos (versión simplificada)
while [ $# -gt 0 ]; do
case $1 in
--email)
email="$2"
shift 2
;;
--puerto)
puerto="$2"
shift 2
;;
--archivo)
archivo="$2"
shift 2
;;
--directorio)
directorio="$2"
shift 2
;;
*)
echo "Opción desconocida: $1"
exit 1
;;
esac
done
# Validar todos los campos
local errores=0
if [ -n "$email" ]; then
if ! validar_email "$email"; then
((errores++))
fi
fi
if [ -n "$puerto" ]; then
if ! validar_puerto "$puerto"; then
((errores++))
fi
fi
if [ -n "$archivo" ]; then
if ! validar_archivo "$archivo"; then
((errores++))
fi
fi
if [ -n "$directorio" ]; then
if ! validar_directorio "$directorio"; then
((errores++))
fi
fi
# Salir si hay errores
if [ $errores -gt 0 ]; then
echo "Se encontraron $errores error(es) en la validación"
exit 1
fi
echo "Todas las validaciones pasaron correctamente"
}
# Ejecutar función principal con todos los argumentos
main "$@"
Crea un script que:
Desarrolla un script que: