Parámetros y argumentos: $1, $@, $#, $?, shift, getopts
Introducción
Los scripts reciben información del exterior a través de los argumentos de la línea de comandos y de variables especiales que bash rellena automáticamente. Dominar estos mecanismos permite escribir scripts reutilizables y flexibles.
Parámetros posicionales
#!/usr/bin/env bash
# Ejecutar como: ./script.sh arg1 arg2 arg3
echo "Nombre del script: $0"
echo "Primer argumento: $1"
echo "Segundo argumento: $2"
echo "Tercer argumento: $3"
Para acceder a parámetros desde el décimo en adelante se necesitan llaves: {$10}, {$11}...
Variables especiales
$0 ← nombre del script (o del shell si no hay script)
$1..$N ← argumentos posicionales
$# ← número total de argumentos
$@ ← todos los argumentos como palabras separadas (recomendado)
$* ← todos los argumentos como una sola cadena
$? ← código de salida del último comando (0=éxito, distinto de 0=error)
$$ ← PID del proceso actual (del script)
$! ← PID del último proceso lanzado en background
$- ← opciones activas del shell (set -e, etc.)
Diferencia entre $@ y $*:
#!/usr/bin/env bash
# Ejecutar: ./script.sh "primer argumento" segundo tercero
# $@ — cada argumento es una palabra separada (lo correcto)
for arg in "$@"; do
echo "Argumento: $arg"
done
# Salida:
# Argumento: primer argumento
# Argumento: segundo
# Argumento: tercero
# $* — todos los argumentos juntos en una cadena
for arg in "$*"; do
echo "Argumento: $arg"
done
# Salida:
# Argumento: primer argumento segundo tercero
Usar siempre "$@" para iterar argumentos — preserva los argumentos con espacios.
shift — Desplazar argumentos
shift descarta el primer argumento ($1) y desplaza todos los demás una posición
hacia la izquierda. $2 pasa a ser $1, etc. Útil para procesar argumentos uno a uno
en un bucle.
#!/usr/bin/env bash
while [ $# -gt 0 ]; do
echo "Procesando: $1"
shift
done
shift 2 # desplazar 2 posiciones de golpe
Validar argumentos
Siempre comprobar que el script recibe los argumentos necesarios antes de usarlos:
#!/usr/bin/env bash
if [ $# -lt 2 ]; then
echo "Uso: $0 <origen> <destino>" >&2
exit 1
fi
ORIGEN="$1"
DESTINO="$2"
echo "Copiando de $ORIGEN a $DESTINO"
getopts — Opciones estilo Unix
getopts permite procesar opciones con guión al estilo Unix (-v, -f fichero), igual que hacen comandos como ls -la o tar -czf.
#!/usr/bin/env bash
# Uso: ./script.sh [-v] [-f fichero] [-n nombre]
VERBOSE=0
FICHERO=""
NOMBRE=""
while getopts "vf:n:" opcion; do
case $opcion in
v) VERBOSE=1 ;;
f) FICHERO="$OPTARG" ;;
n) NOMBRE="$OPTARG" ;;
?) echo "Uso: $0 [-v] [-f fichero] [-n nombre]" >&2; exit 1 ;;
esac
done
# Desplazar los argumentos procesados
shift $((OPTIND - 1))
[ $VERBOSE -eq 1 ] && echo "Modo verbose activado"
[ -n "$FICHERO" ] && echo "Fichero: $FICHERO"
[ -n "$NOMBRE" ] && echo "Nombre: $NOMBRE"
echo "Argumentos restantes: $@"
Reglas de getopts:
- La cadena de opciones (
"vf:n:") lista las letras válidas. -
Un
:tras la letra indica que esa opción requiere un argumento (guardado en$OPTARG). $OPTINDcontiene el índice del siguiente argumento a procesar.- El
?en elcasecaptura opciones desconocidas.
$? — Código de salida
Cada comando devuelve un código de salida al terminar: 0 significa éxito, cualquier otro valor indica
error. $? contiene el código del último comando ejecutado.
ls /tmp
echo $? # 0 (éxito)
ls /no_existe
echo $? # 2 (error: no existe)
grep "patron" fichero.txt
echo $? # 0 si encontró, 1 si no encontró, 2 si error
# Usar $? directamente
if [ $? -eq 0 ]; then
echo "El comando tuvo éxito"
fi
# Forma más idiomática (sin necesidad de $?)
if grep -q "patron" fichero.txt; then
echo "Patrón encontrado"
fi
Importante: $? se sobreescribe con cada comando. Guardarlo en una variable si se necesita
más tarde: RESULTADO=$?.