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
          

Para leer ficheros línea a línea, usar siempre while IFS= read -r linea; do ... done < fichero — es la forma correcta que preserva espacios y barras invertidas.

Funciones: definición, return, local, ámbito de variables

Índice de la sección

Índice del curso