¿Qué son las Estructuras Condicionales?
Las estructuras condicionales permiten que tu script tome decisiones basadas en diferentes condiciones. Son la base de la programación lógica y te permiten crear scripts que reaccionen de manera diferente según las circunstancias.
En Bash, la estructura condicional principal es if, que puede combinarse con else y elif para crear lógica compleja.
Flujo de una Estructura Condicional
Estructura if Básica
La sintaxis básica de if
en Bash sigue esta estructura:
if [ condición ]; then
# Comandos si la condición es verdadera
comando1
comando2
fi
Elementos Clave
- if: Palabra clave que inicia la condición
- [ condición ]: La condición a evaluar (espacios importantes)
- then: Separa la condición de los comandos
- fi: Termina la estructura condicional (if al revés)
# Ejemplo básico: verificar si un archivo existe
$ cat > verificar_archivo.sh << 'EOF'
#!/bin/bash
archivo="mi_archivo.txt"
if [ -f "$archivo" ]; then
echo "El archivo $archivo existe"
ls -la "$archivo"
fi
EOF
$ chmod +x verificar_archivo.sh
# Crear el archivo para probar
$ touch mi_archivo.txt
$ ./verificar_archivo.sh
El archivo mi_archivo.txt existe
-rw-r--r-- 1 user user 0 oct 15 11:30 mi_archivo.txt
if-else: Dos Caminos
Con else
puedes definir qué hacer cuando la condición es falsa:
if [ condición ]; then
# Si la condición es verdadera
comandos_verdaderos
else
# Si la condición es falsa
comandos_falsos
fi
# Ejemplo: verificar edad para votar
$ cat > verificar_edad.sh << 'EOF'
#!/bin/bash
echo "¿Cuál es tu edad?"
read edad
if [ "$edad" -ge 18 ]; then
echo "¡Puedes votar! Tienes $edad años."
echo "Tu deber cívico te espera."
else
echo "Aún no puedes votar. Te faltan $((18 - edad)) años."
echo "¡Pero puedes prepararte para ser un ciudadano informado!"
fi
EOF
$ chmod +x verificar_edad.sh
$ ./verificar_edad.sh
¿Cuál es tu edad?
16
Aún no puedes votar. Te faltan 2 años.
¡Pero puedes prepararte para ser un ciudadano informado!
elif: Múltiples Condiciones
Cuando necesitas evaluar múltiples condiciones, usa elif
(else if):
if [ condición1 ]; then
# Si condición1 es verdadera
comandos1
elif [ condición2 ]; then
# Si condición1 es falsa pero condición2 es verdadera
comandos2
elif [ condición3 ]; then
# Si condiciones anteriores son falsas pero condición3 es verdadera
comandos3
else
# Si todas las condiciones son falsas
comandos_por_defecto
fi
# Ejemplo: clasificador de calificaciones
$ cat > calificaciones.sh << 'EOF'
#!/bin/bash
echo "Introduce tu calificación (0-100):"
read calificacion
if [ "$calificacion" -ge 90 ]; then
echo "¡Excelente! Calificación: A ($calificacion)"
echo "🎉 ¡Felicitaciones por tu dedicación!"
elif [ "$calificacion" -ge 80 ]; then
echo "¡Muy bien! Calificación: B ($calificacion)"
echo "👍 Buen trabajo, sigue así."
elif [ "$calificacion" -ge 70 ]; then
echo "Bien. Calificación: C ($calificacion)"
echo "📚 Con un poco más de esfuerzo puedes mejorar."
elif [ "$calificacion" -ge 60 ]; then
echo "Suficiente. Calificación: D ($calificacion)"
echo "⚠️ Necesitas estudiar más."
else
echo "Insuficiente. Calificación: F ($calificacion)"
echo "❌ Debes prepararte mejor para el próximo examen."
fi
EOF
$ chmod +x calificaciones.sh
$ ./calificaciones.sh
Introduce tu calificación (0-100):
85
¡Muy bien! Calificación: B (85)
👍 Buen trabajo, sigue así.
Operadores de Comparación
Bash ofrece diferentes operadores para comparar números, cadenas y archivos:
Comparaciones Numéricas
Operador | Significado | Ejemplo | Verdadero si |
---|---|---|---|
-eq |
Igual a | [ $a -eq $b ] |
a es igual a b |
-ne |
No igual a | [ $a -ne $b ] |
a no es igual a b |
-gt |
Mayor que | [ $a -gt $b ] |
a es mayor que b |
-ge |
Mayor o igual que | [ $a -ge $b ] |
a es mayor o igual que b |
-lt |
Menor que | [ $a -lt $b ] |
a es menor que b |
-le |
Menor o igual que | [ $a -le $b ] |
a es menor o igual que b |
Comparaciones de Cadenas
Operador | Significado | Ejemplo | Verdadero si |
---|---|---|---|
= |
Cadenas iguales | [ "$a" = "$b" ] |
a es igual a b |
!= |
Cadenas diferentes | [ "$a" != "$b" ] |
a es diferente de b |
-z |
Cadena vacía | [ -z "$a" ] |
a está vacía |
-n |
Cadena no vacía | [ -n "$a" ] |
a no está vacía |
Pruebas de Archivos
Operador | Significado | Ejemplo | Verdadero si |
---|---|---|---|
-e |
Existe | [ -e "$archivo" ] |
el archivo existe |
-f |
Es archivo regular | [ -f "$archivo" ] |
es un archivo regular |
-d |
Es directorio | [ -d "$directorio" ] |
es un directorio |
-r |
Es legible | [ -r "$archivo" ] |
tienes permiso de lectura |
-w |
Es escribible | [ -w "$archivo" ] |
tienes permiso de escritura |
-x |
Es ejecutable | [ -x "$archivo" ] |
tienes permiso de ejecución |
# Ejemplos de diferentes tipos de comparaciones
$ cat > comparaciones_demo.sh << 'EOF'
#!/bin/bash
# Comparaciones numéricas
a=10
b=20
if [ $a -lt $b ]; then
echo "$a es menor que $b"
fi
# Comparaciones de cadenas
usuario="admin"
if [ "$usuario" = "admin" ]; then
echo "Acceso de administrador concedido"
fi
# Verificación de archivos
archivo="/etc/passwd"
if [ -f "$archivo" ]; then
echo "El archivo $archivo existe y es un archivo regular"
if [ -r "$archivo" ]; then
echo "Y además puedo leerlo"
echo "Primeras 3 líneas:"
head -3 "$archivo"
fi
fi
# Verificación de variables vacías
variable_vacia=""
if [ -z "$variable_vacia" ]; then
echo "La variable está vacía"
fi
EOF
$ chmod +x comparaciones_demo.sh
$ ./comparaciones_demo.sh
10 es menor que 20
Acceso de administrador concedido
El archivo /etc/passwd existe y es un archivo regular
Y además puedo leerlo
Primeras 3 líneas:
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
Sintaxis Alternativa: [[ ]]
Bash ofrece una sintaxis extendida con [[ ]]
que es más potente y flexible que [ ]
:
# Sintaxis tradicional [ ]
if [ "$var" = "valor" ]; then
echo "Coincidencia con [ ]"
fi
# Sintaxis extendida [[ ]]
if [[ $var == "valor" ]]; then
echo "Coincidencia con [[ ]]"
fi
# Ventajas de [[ ]]
nombre="Juan Pérez"
# Con [ ] necesitas comillas obligatorias
if [ "$nombre" = "Juan Pérez" ]; then
echo "Nombre correcto con [ ]"
fi
# Con [[ ]] las comillas son opcionales para variables
if [[ $nombre == "Juan Pérez" ]]; then
echo "Nombre correcto con [[ ]]"
fi
# Patrones con [[ ]]
if [[ $nombre == Juan* ]]; then
echo "El nombre empieza con 'Juan'"
fi
# Expresiones regulares con [[ ]]
if [[ $nombre =~ ^[A-Z][a-z]+ ]]; then
echo "El nombre tiene formato válido"
fi
Portabilidad
[[ ]]
es específico de Bash y no está disponible en todos los shells. Si necesitas compatibilidad con sh, usa [ ]
.
Casos Prácticos Reales
#!/bin/bash
# Script para validar y crear usuarios
echo "=== Sistema de Gestión de Usuarios ==="
echo "Introduce el nombre de usuario a crear:"
read nuevo_usuario
# Validar que no esté vacío
if [[ -z "$nuevo_usuario" ]]; then
echo "❌ Error: El nombre de usuario no puede estar vacío."
exit 1
fi
# Validar formato del usuario (solo letras y números)
if [[ ! $nuevo_usuario =~ ^[a-zA-Z][a-zA-Z0-9_]{2,31}$ ]]; then
echo "❌ Error: Formato de usuario inválido."
echo " - Debe empezar con letra"
echo " - Solo letras, números y guiones bajos"
echo " - Entre 3 y 32 caracteres"
exit 1
fi
# Verificar si el usuario ya existe
if id "$nuevo_usuario" &>/dev/null; then
echo "⚠️ El usuario '$nuevo_usuario' ya existe."
echo "¿Deseas ver su información? (s/n):"
read respuesta
if [[ $respuesta =~ ^[sS] ]]; then
echo "Información del usuario:"
id "$nuevo_usuario"
getent passwd "$nuevo_usuario"
fi
else
echo "✅ El usuario '$nuevo_usuario' está disponible."
echo "¿Deseas crearlo ahora? (s/n):"
read crear
if [[ $crear =~ ^[sS] ]]; then
# Verificar si somos root
if [[ $EUID -eq 0 ]]; then
useradd -m "$nuevo_usuario"
echo "✅ Usuario '$nuevo_usuario' creado exitosamente."
else
echo "⚠️ Necesitas permisos de root para crear usuarios."
echo "Ejecuta: sudo useradd -m $nuevo_usuario"
fi
fi
fi
#!/bin/bash
# Monitor de espacio en disco con alertas
UMBRAL_CRITICO=90
UMBRAL_ADVERTENCIA=80
DIRECTORIO=${1:-/}
echo "=== Monitor de Espacio en Disco ==="
echo "Analizando: $DIRECTORIO"
echo "Umbrales: Advertencia=${UMBRAL_ADVERTENCIA}%, Crítico=${UMBRAL_CRITICO}%"
echo
# Obtener porcentaje de uso
uso=$(df "$DIRECTORIO" | awk 'NR==2 {print $5}' | sed 's/%//')
# Verificar si obtuvimos un número válido
if [[ ! $uso =~ ^[0-9]+$ ]]; then
echo "❌ Error: No se pudo obtener información de $DIRECTORIO"
exit 1
fi
echo "Uso actual: ${uso}%"
# Evaluar el nivel de uso
if [[ $uso -ge $UMBRAL_CRITICO ]]; then
echo "🔴 CRÍTICO: Espacio en disco muy bajo!"
echo " Acción requerida inmediatamente."
# Mostrar archivos más grandes
echo
echo "Archivos más grandes en $DIRECTORIO:"
find "$DIRECTORIO" -type f -printf '%s %p\n' 2>/dev/null | sort -nr | head -5 | while read size path; do
echo " $(numfmt --to=iec $size) - $path"
done
elif [[ $uso -ge $UMBRAL_ADVERTENCIA ]]; then
echo "🟡 ADVERTENCIA: Espacio en disco bajo."
echo " Considera limpiar archivos innecesarios."
# Sugerencias de limpieza
echo
echo "Sugerencias de limpieza:"
if [[ -d /tmp ]]; then
tmp_size=$(du -sh /tmp 2>/dev/null | cut -f1)
echo " - Limpiar /tmp (actualmente: $tmp_size)"
fi
if command -v apt-get >/dev/null; then
echo " - Ejecutar: sudo apt-get clean"
fi
else
echo "✅ NORMAL: Espacio en disco suficiente."
fi
# Mostrar información detallada
echo
echo "Detalles del sistema de archivos:"
df -h "$DIRECTORIO"
Ejercicios Prácticos
Ejercicio 1: Clasificador de Archivos
Crea un script que analice un archivo y determine su tipo y características:
#!/bin/bash
# Plantilla para ejercicio de clasificación de archivos
echo "Introduce la ruta del archivo a analizar:"
read archivo
# TODO: Verificar si el archivo existe
if [[ ___ ]]; then
echo "❌ Error: El archivo no existe."
exit 1
fi
# TODO: Determinar el tipo de archivo
if [[ ___ ]]; then
echo "📁 Es un directorio"
echo " Contiene $(ls -1 "$archivo" | wc -l) elementos"
elif [[ ___ ]]; then
echo "📄 Es un archivo regular"
# TODO: Analizar el tamaño
tamaño=$(stat -f%z "$archivo" 2>/dev/null || stat -c%s "$archivo" 2>/dev/null)
if [[ $tamaño ___ 1048576 ]]; then # 1MB
echo " 📦 Archivo grande ($(numfmt --to=iec $tamaño))"
elif [[ $tamaño ___ 1024 ]]; then # 1KB
echo " 📋 Archivo mediano ($(numfmt --to=iec $tamaño))"
else
echo " 📄 Archivo pequeño ($tamaño bytes)"
fi
# TODO: Verificar permisos
if [[ -r "$archivo" ]]; then
echo " ✅ Legible"
fi
if [[ ___ ]]; then
echo " ✅ Escribible"
fi
if [[ ___ ]]; then
echo " ✅ Ejecutable"
fi
else
echo "❓ Tipo de archivo especial"
fi
# DESAFÍO: Agregar detección de extensión y tipo MIME
Ejercicio 2: Sistema de Login
Desarrolla un sistema básico de autenticación:
#!/bin/bash
# Sistema de login básico
USUARIO_ADMIN="admin"
PASSWORD_ADMIN="secreto123"
USUARIO_INVITADO="guest"
PASSWORD_INVITADO="guest"
intentos=0
max_intentos=3
echo "=== Sistema de Acceso ==="
while [[ $intentos -lt $max_intentos ]]; do
echo
echo "Introduce tu usuario:"
read usuario
echo "Introduce tu contraseña:"
read -s password # -s oculta la entrada
# TODO: Implementar la lógica de validación
if [[ "$usuario" == "$USUARIO_ADMIN" && "$password" == "$PASSWORD_ADMIN" ]]; then
echo
echo "✅ Bienvenido, Administrador!"
echo "Tienes acceso completo al sistema."
break
elif [[ ___ ]]; then
echo
echo "✅ Bienvenido, Invitado!"
echo "Tienes acceso limitado al sistema."
break
else
((intentos++))
restantes=$((max_intentos - intentos))
if [[ $restantes -gt 0 ]]; then
echo "❌ Credenciales incorrectas. Te quedan $restantes intentos."
else
echo "❌ Máximo de intentos alcanzado. Acceso bloqueado."
exit 1
fi
fi
done
# TODO: Agregar funcionalidad específica según el tipo de usuario
Ejercicio Avanzado: Backup Inteligente
Crea un script de respaldo que tome decisiones basadas en múltiples condiciones:
- Verificar espacio disponible antes del respaldo
- Decidir tipo de compresión según el tamaño
- Manejar diferentes tipos de archivo
- Implementar rotación de respaldos antiguos