Bucles: for, while, until, break, continue
Introducción
Los bucles permiten repetir bloques de código. Bash ofrece tres tipos: for
para iterar sobre listas, while para repetir mientras se cumpla una condición, y until para repetir hasta que se cumpla.
for — Iterar sobre una lista
Forma básica (lista de valores):
for VARIABLE in LISTA; do
# comandos
done
# Iterar sobre valores literales
for color in rojo verde azul; do
echo "Color: $color"
done
# Iterar sobre ficheros (globbing)
for fichero in /etc/*.conf; do
echo "Configuración: $fichero"
done
# Iterar sobre argumentos del script
for arg in "$@"; do
echo "Argumento: $arg"
done
# Iterar sobre la salida de un comando
for usuario in $(cut -d: -f1 /etc/passwd); do
echo "Usuario: $usuario"
done
Forma numérica estilo C:
for ((i=1; i<=5; i++)); do
echo "Iteración $i"
done
# Con paso diferente
for ((i=0; i<=20; i+=5)); do
echo "$i"
done
Con seq para rangos:
for i in $(seq 1 10); do
echo "$i"
done
# Expansión de rango en bash (sin seq)
for i in {1..10}; do
echo "$i"
done
# Con paso
for i in {0..20..5}; do
echo "$i"
done
while — Repetir mientras la condición sea verdadera
while CONDICIÓN; do
# comandos
done
# Contador
CONTADOR=1
while [ $CONTADOR -le 5 ]; do
echo "Vuelta $CONTADOR"
((CONTADOR++))
done
# Leer fichero línea a línea (forma correcta)
while IFS= read -r linea; do
echo "Línea: $linea"
done < /etc/hosts
# Bucle infinito con break
while true; do
read -p "Introduce un número (0 para salir): " NUM
[ "$NUM" -eq 0 ] && break
echo "El doble es $((NUM * 2))"
done
# Esperar a que un proceso termine
while kill -0 $PID 2>/dev/null; do
echo "El proceso $PID sigue en ejecución..."
sleep 5
done
echo "El proceso ha terminado"
until — Repetir hasta que la condición sea verdadera
Lo contrario de while: se ejecuta mientras la condición sea falsa
y se detiene cuando pasa a ser verdadera.
CONTADOR=1
until [ $CONTADOR -gt 5 ]; do
echo "Vuelta $CONTADOR"
((CONTADOR++))
done
# Esperar a que un servidor esté disponible
until ping -c1 -W1 192.168.1.1 >/dev/null 2>&1; do
echo "Esperando que el servidor esté disponible..."
sleep 3
done
echo "Servidor disponible"
break y continue
break — Salir del bucle:
for i in {1..10}; do
if [ $i -eq 5 ]; then
echo "Encontrado 5, saliendo del bucle"
break
fi
echo "i = $i"
done
# break N — salir de N niveles de bucles anidados
for i in {1..3}; do
for j in {1..3}; do
[ $j -eq 2 ] && break 2 # sale de ambos bucles
echo "$i $j"
done
done
continue — Saltar a la siguiente iteración:
# Procesar solo ficheros .log
for fichero in /var/log/*; do
[[ "$fichero" != *.log ]] && continue
echo "Procesando: $fichero"
# ... procesamiento del log
done
# Saltar números pares
for i in {1..10}; do
(( i % 2 == 0 )) && continue
echo "Impar: $i"
done
Patrones prácticos
Leer fichero CSV línea a línea:
while IFS=, read -r nombre edad ciudad; do
echo "Nombre: $nombre, Edad: $edad, Ciudad: $ciudad"
done < datos.csv
Procesar múltiples servidores:
SERVIDORES="web01 web02 web03 db01"
for servidor in $SERVIDORES; do
echo "Verificando $servidor..."
ssh "$servidor" "uptime" || echo "ERROR: $servidor no responde"
done
Reintentar un comando hasta que tenga éxito:
INTENTOS=0
MAX=5
until curl -sf https://api.ejemplo.com/health; do
((INTENTOS++))
[ $INTENTOS -ge $MAX ] && { echo "Falló tras $MAX intentos" >&2; exit 1; }
echo "Reintento $INTENTOS/$MAX..."
sleep 10
done