Bucles for, while y until

Domina la automatización con bucles para ejecutar tareas repetitivas

Módulo 3 ⏱️ 35-40 min 🔄 Bucles 🔀 Control 📚 Intermedio

¿Qué son los Bucles?

Los bucles son estructuras de control que nos permiten repetir una secuencia de comandos múltiples veces. Son fundamentales para la automatización, ya que nos evitan escribir el mismo código repetidamente y nos permiten procesar grandes cantidades de datos de manera eficiente.

Bash proporciona tres tipos principales de bucles: for, while y until. Cada uno tiene sus casos de uso específicos y características únicas.

Comparación de Tipos de Bucles

Bucle FOR

Uso: Cuando conoces de antemano cuántas veces quieres repetir algo o tienes una lista específica de elementos.

Ejemplo: Procesar cada archivo en un directorio, iterar números del 1 al 10.

Bucle WHILE

Uso: Cuando quieres repetir mientras una condición sea verdadera.

Ejemplo: Leer líneas de un archivo, esperar hasta que un proceso termine.

Bucle UNTIL

Uso: Cuando quieres repetir hasta que una condición se vuelva verdadera.

Ejemplo: Intentar conectar hasta que la conexión sea exitosa.

Bucle FOR

El bucle for es probablemente el más utilizado. Tiene varias sintaxis dependiendo del caso de uso.

Sintaxis Básica con Lista

Estructura básica del bucle for Copiar
for variable in lista
do
    # comandos a ejecutar
done

Ejemplos Prácticos

Ejemplo 1: Iterar sobre archivos Copiar
#!/bin/bash
# Procesar todos los archivos .txt en el directorio actual
for archivo in *.txt
do
    echo "Procesando: $archivo"
    # Contar líneas del archivo
    lineas=$(wc -l < "$archivo")
    echo "  El archivo $archivo tiene $lineas líneas"
done
$ ./procesar_archivos.sh
Procesando: documento1.txt
  El archivo documento1.txt tiene 25 líneas
Procesando: notas.txt
  El archivo notas.txt tiene 15 líneas
Procesando: readme.txt
  El archivo readme.txt tiene 8 líneas
Ejemplo 2: Iterar sobre números (estilo C) Copiar
#!/bin/bash
# Crear respaldos numerados
for ((i=1; i<=5; i++))
do
    echo "Creando respaldo número $i"
    cp important_file.txt "backup_${i}.txt"
done
Ejemplo 3: Iterar con rangos usando seq Copiar
#!/bin/bash
# Crear directorios del 2023 al 2025
for año in $(seq 2023 2025)
do
    mkdir -p "reportes_$año"
    echo "Directorio reportes_$año creado"
done

# También puedes usar expansión de llaves
for mes in {01..12}
do
    mkdir -p "mes_$mes"
    echo "Directorio mes_$mes creado"
done
Consejo Pro

Siempre usa comillas dobles alrededor de las variables que representen nombres de archivo: "$archivo". Esto previene problemas con espacios en los nombres.

Bucle WHILE

El bucle while ejecuta comandos mientras una condición sea verdadera. Es ideal cuando no sabes exactamente cuántas iteraciones necesitarás.

Estructura básica del bucle while Copiar
while [ condición ]
do
    # comandos a ejecutar
done

Ejemplos Prácticos

Ejemplo 1: Contador simple Copiar
#!/bin/bash
# Contador del 1 al 10
contador=1
while [ $contador -le 10 ]
do
    echo "Iteración número: $contador"
    ((contador++))  # Incrementar contador
done
echo "¡Bucle terminado!"
Ejemplo 2: Leer archivo línea por línea Copiar
#!/bin/bash
# Leer un archivo línea por línea
archivo="datos.txt"
numero_linea=1

while IFS= read -r linea
do
    echo "Línea $numero_linea: $linea"
    ((numero_linea++))
done < "$archivo"
Ejemplo 3: Monitoreo de proceso Copiar
#!/bin/bash
# Esperar hasta que un proceso termine
proceso="mi_aplicacion"

while pgrep "$proceso" > /dev/null
do
    echo "El proceso $proceso sigue corriendo..."
    echo "Esperando 5 segundos..."
    sleep 5
done

echo "El proceso $proceso ha terminado"
$ ./monitor_proceso.sh
El proceso mi_aplicacion sigue corriendo...
Esperando 5 segundos...
El proceso mi_aplicacion sigue corriendo...
Esperando 5 segundos...
El proceso mi_aplicacion ha terminado

Bucle UNTIL

El bucle until es lo opuesto a while: ejecuta comandos hasta que una condición se vuelva verdadera. Es útil cuando queremos repetir algo hasta alcanzar un objetivo.

Estructura básica del bucle until Copiar
until [ condición ]
do
    # comandos a ejecutar
done

Ejemplos Prácticos

Ejemplo 1: Esperar hasta que un archivo exista Copiar
#!/bin/bash
# Esperar hasta que aparezca un archivo
archivo_esperado="/tmp/resultado.txt"

echo "Esperando que aparezca el archivo: $archivo_esperado"
until [ -f "$archivo_esperado" ]
do
    echo "Archivo no encontrado, esperando 2 segundos..."
    sleep 2
done

echo "¡El archivo ha aparecido!"
echo "Contenido del archivo:"
cat "$archivo_esperado"
Ejemplo 2: Reintentar conexión Copiar
#!/bin/bash
# Intentar conectar hasta que funcione
servidor="google.com"
intentos=0

echo "Intentando conectar con $servidor..."
until ping -c 1 "$servidor" &> /dev/null
do
    ((intentos++))
    echo "Intento $intentos fallido, reintentando en 3 segundos..."
    sleep 3
    
    # Limitar intentos para evitar bucle infinito
    if [ $intentos -ge 10 ]; then
        echo "Error: No se pudo conectar después de $intentos intentos"
        exit 1
    fi
done

echo "¡Conexión exitosa con $servidor después de $intentos intentos!"
Cuidado con los Bucles Infinitos

Siempre asegúrate de que la condición del bucle pueda cambiar eventualmente, o incluye un mecanismo de escape como un contador de intentos máximos.

Bucles Anidados

Puedes anidar bucles para crear estructuras más complejas. Esto es útil para operaciones matriciales o procesamiento de estructuras de datos multidimensionales.

Ejemplo: Tabla de multiplicar Copiar
#!/bin/bash
# Generar tabla de multiplicar del 1 al 5
echo "Tabla de multiplicar:"
echo "====================="

for i in {1..5}
do
    for j in {1..5}
    do
        resultado=$((i * j))
        printf "%2d x %2d = %2d   " $i $j $resultado
    done
    echo  # Nueva línea al final de cada fila
done
$ ./tabla_multiplicar.sh
Tabla de multiplicar:
=====================
 1 x  1 =  1    1 x  2 =  2    1 x  3 =  3    1 x  4 =  4    1 x  5 =  5   
 2 x  1 =  2    2 x  2 =  4    2 x  3 =  6    2 x  4 =  8    2 x  5 = 10   
 3 x  1 =  3    3 x  2 =  6    3 x  3 =  9    3 x  4 = 12    3 x  5 = 15   
 4 x  1 =  4    4 x  2 =  8    4 x  3 = 12    4 x  4 = 16    4 x  5 = 20   
 5 x  1 =  5    5 x  2 = 10    5 x  3 = 15    5 x  4 = 20    5 x  5 = 25

Casos de Uso Avanzados

Procesamiento de Archivos
Comprimir archivos antiguos Copiar
#!/bin/bash
# Comprimir archivos modificados hace más de 30 días
for archivo in $(find /var/log -name "*.log" -mtime +30)
do
    if [ -f "$archivo" ]; then
        echo "Comprimiendo: $archivo"
        gzip "$archivo"
        echo "Comprimido: ${archivo}.gz"
    fi
done
Respaldo Automático
Respaldo de bases de datos Copiar
#!/bin/bash
# Lista de bases de datos a respaldar
bases_datos=("usuarios" "productos" "ventas")

for bd in "${bases_datos[@]}"
do
    fecha=$(date +%Y%m%d_%H%M%S)
    archivo_respaldo="${bd}_backup_${fecha}.sql"
    
    echo "Respaldando base de datos: $bd"
    mysqldump -u usuario -p "$bd" > "$archivo_respaldo"
    
    if [ $? -eq 0 ]; then
        echo "✓ Respaldo exitoso: $archivo_respaldo"
    else
        echo "✗ Error en respaldo de: $bd"
    fi
done

Ejercicios Prácticos

Ejercicio 1: Organizador de Archivos

Crea un script que organice archivos por extensión:

organizador.sh Copiar
#!/bin/bash
# Organizar archivos por extensión
directorio_origen="${1:-.}"  # Usa directorio actual si no se especifica

echo "Organizando archivos en: $directorio_origen"

# Crear directorios para diferentes tipos de archivos
for tipo in "imagenes" "documentos" "videos" "audios" "otros"
do
    mkdir -p "$tipo"
done

# Procesar archivos
for archivo in "$directorio_origen"/*
do
    if [ -f "$archivo" ]; then
        nombre=$(basename "$archivo")
        extension="${nombre##*.}"
        
        case "$extension" in
            jpg|jpeg|png|gif|bmp)
                echo "Moviendo imagen: $nombre"
                mv "$archivo" "imagenes/"
                ;;
            pdf|doc|docx|txt|rtf)
                echo "Moviendo documento: $nombre"
                mv "$archivo" "documentos/"
                ;;
            mp4|avi|mkv|mov)
                echo "Moviendo video: $nombre"
                mv "$archivo" "videos/"
                ;;
            mp3|wav|flac|aac)
                echo "Moviendo audio: $nombre"
                mv "$archivo" "audios/"
                ;;
            *)
                echo "Moviendo a otros: $nombre"
                mv "$archivo" "otros/"
                ;;
        esac
    fi
done

echo "¡Organización completa!"
Ejercicio 2: Monitor de Sistema

Crea un script que monitoree el uso de CPU y memoria cada 5 segundos:

monitor.sh Copiar
#!/bin/bash
# Monitor de sistema simple
echo "Monitor de Sistema - Presiona Ctrl+C para salir"
echo "================================================"

contador=0
while true
do
    clear
    echo "Monitor de Sistema - Actualización #$((++contador))"
    echo "Hora: $(date)"
    echo "================================================"
    
    # CPU
    cpu_uso=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | sed 's/%us,//')
    echo "Uso de CPU: ${cpu_uso}%"
    
    # Memoria
    memoria_info=$(free -h | grep "Mem:")
    echo "Memoria: $memoria_info"
    
    # Procesos con más CPU
    echo ""
    echo "Top 5 procesos por CPU:"
    ps aux --sort=-%cpu | head -6
    
    echo ""
    echo "Esperando 5 segundos... (Ctrl+C para salir)"
    sleep 5
done