📚 Módulo 3: Tomando decisiones con tu terminal¶
Duración estimada: 3-4 horas según tu ritmo y experiencia.
Objetivo: Usar condicionales (if, case) para que tus scripts tomen decisiones, y aprender bucles for para automatizar tareas repetitivas. También aprenderás a depurar scripts cuando algo falla. 🎯
Prerrequisitos: Haber completado los Módulos 1 y 2, saber crear y ejecutar scripts básicos con variables y redirecciones.
Nota: Los condicionales y bucles son la base de cualquier script no trivial. Practica cada ejemplo antes de continuar.
📖 Contenidos del Módulo¶
3.1. Condicionales básicos: if y else 🌱¶
Teoría:
Los condicionales permiten ejecutar diferentes bloques de código según una condición. La estructura básica en Bash es:
if [ condición ]; then
# código si la condición es verdadera
else
# código si la condición es falsa
fi
Los corchetes [ ] evalúan la condición. Los operadores más habituales para números son -eq (igual), -ne (distinto), -gt (mayor que), -lt (menor que), -ge (mayor o igual) y -le (menor o igual). Para comparar texto se usa = y !=.
Buena práctica: Escribe siempre las variables entre comillas dentro de los corchetes:
[ "$variable" -gt 5 ]. Así evitas errores si la variable está vacía o contiene espacios.
Práctica:
- Crea un script
decision.sh:
nano decision.sh
- Escribe un condicional básico:
#!/bin/bash
numero=10
if [ "$numero" -gt 5 ]; then
echo "El número es mayor que 5"
else
echo "El número es menor o igual a 5"
fi
Guarda, dale permisos (chmod +x decision.sh) y ejecútalo.
-
Cambia el valor de
numeroa3y vuelve a ejecutar para ver el otro caso. -
Añade una condición intermedia con
elif:
nano decision.sh
#!/bin/bash
numero=5
if [ "$numero" -gt 10 ]; then
echo "Mayor que 10"
elif [ "$numero" -eq 5 ]; then
echo "Exactamente 5"
else
echo "Menor que 5"
fi
- Prueba con distintos valores de
numero(0, 5, 15) para verificar los tres casos.
Consejo:
elifes la abreviatura de "else if". Puedes encadenar tantoselifcomo necesites. 💡
3.2. Condicionales avanzados: case 🖌️¶
Teoría:
case es una alternativa más limpia a encadenar múltiples elif cuando quieres comparar una variable contra varios valores concretos. Su sintaxis es:
case "$variable" in
patron1) comandos ;;
patron2) comandos ;;
*) comandos por defecto ;;
esac
El * actúa como comodín para cualquier valor no contemplado en los patrones anteriores. Es especialmente útil en menús interactivos.
Práctica:
- Crea un script
menu.sh:
nano menu.sh
- Escribe un menú básico con
case:
#!/bin/bash
opcion="salir"
case "$opcion" in
iniciar) echo "Iniciando el sistema..." ;;
detener) echo "Deteniendo el sistema..." ;;
salir) echo "Saliendo..." ;;
*) echo "Opción no reconocida: $opcion" ;;
esac
Guarda, dale permisos y ejecútalo. Luego cambia opcion a iniciar y detener para probar.
- Añade entrada del usuario con
read:
nano menu.sh
#!/bin/bash
read -p "Elige una opción (iniciar/detener/salir): " opcion
case "$opcion" in
iniciar) echo "Iniciando el sistema..." ;;
detener) echo "Deteniendo el sistema..." ;;
salir) echo "¡Hasta luego!" ;;
*) echo "Opción '$opcion' no reconocida." ;;
esac
-
Ejecuta el script varias veces introduciendo diferentes opciones, incluyendo una no válida.
-
Añade un patrón que acepte tanto mayúsculas como minúsculas para
salir:
salir|SALIR) echo "¡Hasta luego!" ;;
El | dentro de case permite múltiples patrones para la misma acción.
Dato curioso:
casees mucho más legible que una cadena larga deelifcuando tienes más de tres opciones. 😄
3.3. Comparando texto y archivos ⚙️¶
Teoría:
Bash permite evaluar condiciones sobre cadenas de texto y sobre el sistema de archivos. Algunos operadores útiles:
[ "$a" = "$b" ]— las cadenas son iguales[ "$a" != "$b" ]— las cadenas son distintas[ -z "$a" ]— la cadena está vacía[ -n "$a" ]— la cadena no está vacía[ -f archivo ]— el archivo existe y es un fichero regular[ -d directorio ]— el directorio existe[ -e ruta ]— la ruta existe (archivo o directorio)
Práctica:
- Comprueba si una cadena está vacía:
nano texto.sh
#!/bin/bash
cadena=""
if [ -z "$cadena" ]; then
echo "La cadena está vacía"
else
echo "La cadena contiene: $cadena"
fi
Guarda, dale permisos y prueba cambiando el valor de cadena.
- Verifica si un archivo existe:
nano archivo.sh
#!/bin/bash
if [ -f "salida.txt" ]; then
echo "El archivo salida.txt existe"
else
echo "El archivo salida.txt NO existe"
fi
- Ejecuta el script, luego crea el archivo y vuelve a ejecutarlo:
chmod +x archivo.sh
./archivo.sh
touch salida.txt
./archivo.sh
- Añade una verificación de directorio:
if [ -d "mi_aventura" ]; then
echo "El directorio mi_aventura existe"
fi
- Combina condiciones con
&&(y) y||(o):
nano combo.sh
#!/bin/bash
archivo="salida.txt"
if [ -f "$archivo" ] && [ -n "$archivo" ]; then
echo "El archivo existe y tiene nombre"
fi
Consejo: Comprueba siempre la existencia de archivos antes de trabajar con ellos para evitar errores inesperados en tus scripts. 💡
3.4. Bucles for: Repite con elegancia 📜¶
Teoría:
El bucle for repite un bloque de comandos para cada elemento de una lista. En Bash hay varias formas de usarlo. De menor a mayor complejidad:
# Lista literal
for elemento in uno dos tres; do
echo "$elemento"
done
# Rango con llaves
for i in {1..5}; do
echo "Iteración $i"
done
# Secuencia con seq (útil para rangos dinámicos)
for i in $(seq 1 5); do
echo "Número $i"
done
# Globbing: todos los archivos .sh del directorio
for archivo in *.sh; do
echo "Script: $archivo"
done
Práctica:
- Crea un script
bucle.shcon una lista literal:
nano bucle.sh
#!/bin/bash
for fruta in manzana naranja pera; do
echo "Fruta: $fruta"
done
Guarda, dale permisos y ejecútalo.
- Usa un rango con llaves para contar:
nano bucle.sh
#!/bin/bash
for i in {1..5}; do
echo "Número: $i"
done
- Usa
seqpara un rango con paso personalizado:
nano bucle.sh
#!/bin/bash
# Contar de 2 en 2 hasta 10
for i in $(seq 2 2 10); do
echo "Par: $i"
done
La sintaxis de seq es: seq inicio paso fin.
- Recorre todos los scripts del directorio con globbing:
nano bucle.sh
#!/bin/bash
for archivo in *.sh; do
echo "Encontrado: $archivo"
done
- Crea varios archivos en un bucle y luego lístalos:
nano crear.sh
#!/bin/bash
for i in {1..3}; do
touch "archivo_$i.txt"
echo "Creado archivo_$i.txt"
done
ls *.txt
Consejo: Usa
{inicio..fin}para rangos simples y$(seq inicio paso fin)cuando el inicio o el fin sean variables. 💡
3.5. Depuración: Encuentra y corrige errores 🚀¶
Teoría:
Bash incluye opciones de depuración muy útiles que se activan con el flag -x (modo trace). Puedes usarlo al ejecutar el script o añadirlo en el propio código:
bash -x script.sh— muestra cada comando antes de ejecutarlo.set -xdentro del script — activa el trace desde ese punto.set +x— desactiva el trace.set -e— hace que el script se detenga inmediatamente si cualquier comando falla.
Práctica:
- Crea un script con un error intencional:
nano error.sh
#!/bin/bash
echo "Inicio del script"
ls /ruta/inexistente
echo "Fin del script"
Ejecútalo y observa qué pasa: el error se muestra pero el script continúa.
- Activa el modo trace para ver qué ejecuta cada línea:
bash -x error.sh
Cada línea precedida por + muestra el comando que se va a ejecutar.
- Añade
set -epara detener el script en el primer error:
nano error.sh
#!/bin/bash
set -e
echo "Inicio del script"
ls /ruta/inexistente
echo "Esta línea NO se ejecutará"
- Combina
set -eyset -xpara depuración completa:
nano debug.sh
#!/bin/bash
set -ex
nombre="Debug"
echo "Hola, $nombre"
ls /tmp
- Usa
set -xyset +xpara depurar solo una sección:
nano parcial.sh
#!/bin/bash
echo "Sección normal"
set -x
ls /tmp
set +x
echo "Vuelvo al modo normal"
Advertencia: Quita
set -xantes de pasar el script a producción; el trace genera mucho ruido en los logs. 🛑
🛠️ Ejercicios prácticos¶
- Condicional: Crea un script que compruebe si un archivo
datos.txtexiste y muestre un mensaje apropiado en cada caso. - Case: Escribe un menú de 4 opciones (crear, listar, borrar, salir) que muestre un mensaje para cada una.
- Bucle: Crea un script que genere los archivos
nota_1.txthastanota_5.txtcon el texto "Nota número N". - Depuración: Introduce un error en uno de tus scripts y usa
bash -xpara localizarlo. - Desafío: Crea un script que liste los archivos
.txtdel directorio y muestre si cada uno está vacío o no (pista:[ -s archivo ]comprueba si el archivo tiene contenido).
📝 Evaluación¶
Cuestionario (5 preguntas):
- ¿Cuándo usarías
caseen lugar deif/elif? - ¿Qué hace
[ -f archivo ]en una condición? - ¿Cómo recorres todos los archivos
.txtde un directorio confor? - ¿Para qué sirve
bash -x script.sh? - ¿Qué diferencia hay entre
{1..5}y$(seq 1 5)?
Tarea práctica:
Crea un script organiza.sh que:
- Compruebe si existe una carpeta backup; si no, la cree.
- Recorra todos los archivos .txt del directorio actual y los copie a backup/.
- Muestre un mensaje al finalizar indicando cuántos archivos copió.
Entrega: El script y una breve explicación de cómo funciona cada sección.
🎬 Vídeo con la solución de la evaluación: Próximamente.
🎉 Recursos adicionales¶
- Documentación:
man bash(sección "Compound Commands"). - Referencia de condicionales: Bash Conditional Expressions (GNU).
- Práctica interactiva: ShellCheck — analiza tus scripts y señala errores comunes en tiempo real.
Tip: ShellCheck es una herramienta gratuita que detecta errores frecuentes en scripts Bash antes de ejecutarlos. Úsala siempre que tengas dudas. 💡
🚀 Siguientes pasos¶
¡Felicidades por completar el Módulo 3! En el Módulo 4 aprenderás a procesar texto con herramientas como grep, sed y awk, y a trabajar con expresiones regulares. ¡El procesamiento de datos te espera! ✍️