Home / Sistemas / Guia Completa de Condicionales If Else en Bash para Scripts Linux
Guia Completa de Condicionales If Else en Bash para Scripts Linux

Guia Completa de Condicionales If Else en Bash para Scripts Linux

14 October 2026 · 13 min de lectura ··

Introduccion a las sentencias condicionales en Bash

Las sentencias condicionales constituyen uno de los pilares fundamentales de cualquier lenguaje de programacion o de scripting. En el caso de Bash, el shell por defecto en la mayoria de distribuciones Linux modernas, permiten que un script tome decisiones en tiempo de ejecucion en funcion de valores de variables, resultados de comandos, existencia de archivos o cualquier otra condicion evaluable. Esta capacidad de ramificacion transforma un conjunto lineal de instrucciones en un programa dinamico capaz de adaptarse a diferentes escenarios.

En 2026 Bash continua siendo una herramienta esencial para administradores de sistemas, desarrolladores DevOps y cualquier persona que necesite automatizar tareas en entornos Linux o Unix. Aunque existen alternativas como Zsh o lenguajes de mas alto nivel, Bash permanece como el estandar de facto para scripts de sistema, pipelines de CI/CD y utilidades de linea de comandos. Comprender a fondo la sintaxis de if, elif y else resulta indispensable para escribir scripts robustos, legibles y libres de errores comunes.

A lo largo de esta guia exploraremos desde la sintaxis basica hasta tecnicas avanzadas recomendadas en la actualidad. Prestaremos especial atencion a las diferencias entre los operadores de prueba tradicionales y las construcciones modernas de Bash, asi como a las practicas que evitan los fallos mas frecuentes relacionados con expansiones de variables no entrecomilladas o condiciones mal formadas. El objetivo es proporcionar un recurso completo y actualizado que permita implementar logica condicional de forma profesional en scripts de produccion.

Sintaxis basica de la sentencia if

La forma mas sencilla de una sentencia condicional en Bash evalua una condicion y, si esta se cumple, ejecuta un bloque de comandos. La estructura general se escribe de la siguiente manera:

if CONDICION; then
    comandos
fi

La palabra clave if inicia la evaluacion, then marca el inicio del bloque verdadero y fi cierra la construccion. El punto y coma antes de then es opcional cuando then se coloca en la linea siguiente. Bash trata cualquier comando como una condicion: el codigo de salida cero se considera verdadero y cualquier valor distinto de cero se considera falso.

Un ejemplo minimalista que verifica si un numero es positivo podria escribirse asi:

#!/usr/bin/env bash
numero=42
if (( numero > 0 )); then
    echo "El numero es positivo"
fi

En este caso se utiliza la evaluacion aritmetica con doble parentesis, una de las formas recomendadas en la actualidad para comparaciones numericas. Si se ejecuta el script, la condicion se cumple y se muestra el mensaje correspondiente.

La salida del ejemplo anterior es:

El numero es positivo

Es importante recordar que los espacios alrededor de los operadores y las palabras clave forman parte de la sintaxis y no pueden omitirse. Un error tipico de principiantes consiste en escribir if[ condicion ] sin espacios, lo que genera un mensaje de comando no encontrado.

Uso de if else para manejar el caso contrario

Cuando se desea ejecutar un bloque de codigo solo cuando la condicion no se cumple, se anade la clausula else. Esta estructura cubre ambos caminos posibles de una decision binaria y resulta extremadamente comun en scripts de validacion o de configuracion.

La sintaxis completa queda de la siguiente forma:

if CONDICION; then
    comandos si verdadero
else
    comandos si falso
fi

Consideremos un script que solicita un numero al usuario y determina si es par o impar:

#!/usr/bin/env bash
set -euo pipefail
read -r -p "Introduce un numero entero: " numero
if (( numero % 2 == 0 )); then
    echo "El numero $numero es par"
else
    echo "El numero $numero es impar"
fi

La opcion set -euo pipefail activa un modo estricto que aborta el script ante errores, variables no definidas o fallos en tuberias. Esta practica se considera estandar en scripts modernos de 2026. El operador % calcula el residuo de la division entera. Si el usuario introduce 7, el resultado es impar; si introduce 10, el resultado es par.

Otro caso practico frecuente es la verificacion de existencia de un archivo de configuracion antes de intentar leerlo:

#!/usr/bin/env bash
config="./app.conf"
if [[ -f "$config" ]]; then
    echo "Archivo de configuracion encontrado"
else
    echo "Archivo de configuracion ausente, se usara valores por defecto"
fi

Aqui se emplea la prueba de archivo -f dentro de doble corchete. Esta forma es preferible porque evita problemas de division de palabras y expansion de globos. El entrecomillado de la variable, aunque no estrictamente necesario dentro de [[]], se mantiene por consistencia y legibilidad.

Extension con elif para multiples condiciones

Cuando una decision requiere mas de dos caminos, se utiliza elif (else if). Bash evalua las condiciones de arriba hacia abajo y ejecuta el primer bloque cuya condicion sea verdadera. El else final, si existe, actua como caso por defecto.

La estructura general es:

if CONDICION1; then
    bloque1
elif CONDICION2; then
    bloque2
elif CONDICION3; then
    bloque3
else
    bloque por defecto
fi

Un ejemplo clasico consiste en clasificar un numero introducido por el usuario como positivo, negativo o cero:

#!/usr/bin/env bash
set -euo pipefail
read -r -p "Introduce un numero: " num
if [[ ! "$num" =~ ^-?[0-9]+$ ]]; then
    echo "Error: entrada no valida" >&2
    exit 1
fi
if (( num > 0 )); then
    echo "Positivo"
elif (( num < 0 )); then
    echo "Negativo"
else
    echo "Cero"
fi

La expresion regular dentro de [[]] valida que la entrada sea un entero antes de realizar comparaciones aritmeticas. Esta validacion previa evita errores de ejecucion y constituye una buena practica en cualquier script que acepte entrada del usuario. Si se introduce el valor 15, se muestra Positivo; si se introduce -3, se muestra Negativo; si se introduce 0, se muestra Cero.

Otro escenario tipico es la seleccion de modo de ejecucion a partir de una variable de entorno:

#!/usr/bin/env bash
APP_MODE="${APP_MODE:-dev}"
if [[ "$APP_MODE" == "prod" ]]; then
    echo "Ejecutando en modo produccion"
elif [[ "$APP_MODE" == "staging" ]]; then
    echo "Ejecutando en modo staging"
else
    echo "Ejecutando en modo desarrollo"
fi

La expansion ${APP_MODE:-dev} asigna el valor por defecto dev cuando la variable no esta definida. Este patron reduce la necesidad de condiciones adicionales para comprobar si la variable existe.

Operadores de comparacion numerica y de cadenas

Bash ofrece diferentes conjuntos de operadores segun el tipo de dato que se desea comparar. Para numeros enteros se pueden utilizar operadores aritmeticos dentro de (( )) o los operadores de prueba tradicionales dentro de [ ] o [[]].

Dentro de la evaluacion aritmetica (( )) se emplean los simbolos habituales de la mayoria de lenguajes:

if (( a > b )); then
    echo "a es mayor"
fi
if (( a == b )); then
    echo "a es igual a b"
fi
if (( a <= 10 )); then
    echo "a es menor o igual a 10"
fi

Estos operadores no requieren entrecomillado y permiten expresiones mas complejas como (( a * 2 + 5 > b )).

Para cadenas de texto, los operadores mas usados dentro de [[]] son == y !=. Ademas, Bash admite coincidencia de patrones:

nombre="archivo.log"
if [[ "$nombre" == *.log ]]; then
    echo "Es un archivo de registro"
fi

El asterisco sin entrecomillar actua como comodin. Si se desea una comparacion literal, se entrecomilla el patron. La expresion regular se introduce con el operador =~:

if [[ "$email" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
    echo "Formato de correo valido"
fi

Estas capacidades de coincidencia de patrones y expresiones regulares dentro de [[]] constituyen una de las razones principales por las que se recomienda esta construccion sobre el test tradicional [ ] en scripts orientados a Bash.

Pruebas de archivos y directorios

Una de las aplicaciones mas frecuentes de las sentencias condicionales en Bash es la verificacion del sistema de archivos. Los operadores de prueba permiten comprobar existencia, tipo, permisos y otras propiedades.

Los operadores mas habituales son:

  • -e : el archivo o directorio existe
  • -f : es un archivo regular
  • -d : es un directorio
  • -r : tiene permiso de lectura
  • -w : tiene permiso de escritura
  • -x : tiene permiso de ejecucion
  • -s : existe y tiene tamano mayor que cero

Un script que prepara un directorio de trabajo antes de continuar podria verse asi:

#!/usr/bin/env bash
set -euo pipefail
workdir="/tmp/trabajo"
if [[ ! -d "$workdir" ]]; then
    mkdir -p "$workdir"
    echo "Directorio creado"
else
    echo "Directorio ya existente"
fi
if [[ -w "$workdir" ]]; then
    echo "El directorio es escribible"
else
    echo "Sin permisos de escritura" >&2
    exit 1
fi

La combinacion de ! con -d invierte la condicion. El uso de mkdir -p evita errores si el directorio padre no existe. Este tipo de verificaciones defensivas resulta esencial en scripts de despliegue o de procesamiento de datos.

Otro ejemplo util consiste en comprobar si un archivo de bloqueo existe antes de iniciar un proceso que no debe ejecutarse en paralelo:

#!/usr/bin/env bash
lockfile="/tmp/mi_script.lock"
if [[ -e "$lockfile" ]]; then
    echo "El proceso ya se esta ejecutando" >&2
    exit 1
fi
touch "$lockfile"
trap 'rm -f "$lockfile"' EXIT
# resto del script

El trap garantiza que el archivo de bloqueo se elimine incluso si el script termina de forma anormal. Esta tecnica se emplea ampliamente en automatizaciones de sistema.

Combinacion de condiciones con operadores logicos

Bash permite combinar varias condiciones mediante && (and), || (or) y ! (not). Dentro de [[]] estos operadores funcionan de forma directa y con cortocircuito, lo que mejora la legibilidad y el rendimiento.

Un ejemplo que verifica dos condiciones simultaneas:

edad=25
miembro="si"
if [[ $edad -ge 18 && $miembro == "si" ]]; then
    echo "Acceso permitido"
fi

La misma logica puede escribirse con el operador tradicional -a dentro de [ ], aunque esta forma es menos recomendable:

if [ "$edad" -ge 18 -a "$miembro" = "si" ]; then
    echo "Acceso permitido"
fi

Para condiciones mas complejas se pueden agrupar expresiones con parentesis dentro de [[]]:

if [[ ( $edad -gt 60 || $edad -lt 12 ) && $miembro == "si" ]]; then
    echo "Descuento especial aplicable"
fi

Es posible anidar varias sentencias if cuando la logica lo requiere, aunque suele preferirse elif o case cuando el numero de ramas crece. Un ejemplo de anidamiento moderado:

#!/usr/bin/env bash
if [[ -f "$archivo" ]]; then
    if [[ -r "$archivo" ]]; then
        echo "Archivo legible"
    else
        echo "Archivo no legible"
    fi
else
    echo "Archivo no existe"
fi

En la practica, las condiciones anidadas deben mantenerse poco profundas para preservar la legibilidad del codigo.

Mejores practicas modernas para condicionales en Bash

Las recomendaciones actuales de la comunidad de Bash enfatizan varias practicas que reducen errores y mejoran la mantenibilidad. En primer lugar, se prefiere [[]] sobre [ ] en scripts que declaran el shebang #!/usr/bin/env bash o #!/bin/bash. La construccion [[]] evita la division de palabras y la expansion de nombres de archivo, y ofrece operadores adicionales.

En segundo lugar, para comparaciones numericas puras se recomienda (( )). Esta forma es mas rapida y permite una sintaxis mas natural. Solo se recurre a los operadores -eq, -gt, etc., cuando se necesita compatibilidad con sh POSIX.

En tercer lugar, todas las variables deben entrecomillarse en contextos donde la expansion pueda alterar el numero de argumentos. Aunque [[]] es mas tolerante, el habito de entrecomillar siempre evita confusiones al cambiar de contexto.

El modo estricto set -euo pipefail debe colocarse al inicio de cada script. Este conjunto de opciones hace que el script falle rapidamente ante errores, lo que facilita la depuracion. Cuando un comando puede fallar de forma esperada (por ejemplo, grep sin coincidencias), se captura el codigo de salida de forma explicita:

if ! grep -q "$patron" "$archivo"; then
    status=$?
    if (( status == 1 )); then
        echo "No se encontraron coincidencias"
    else
        echo "Error en grep: $status" >&2
        exit "$status"
    fi
fi

Finalmente, se recomienda validar toda entrada externa antes de usarla en condiciones o en comandos. Las expresiones regulares dentro de [[]] o las funciones de validacion dedicadas cumplen esta funcion de manera eficaz.

Alternativas y patrones complementarios

Aunque if, elif y else cubren la mayoria de necesidades, existen construcciones relacionadas que conviene conocer. La sentencia case resulta especialmente util cuando se compara una sola variable contra varios patrones fijos:

case "$OSTYPE" in
    linux*)
        echo "Sistema Linux"
        ;;
    darwin*)
        echo "Sistema macOS"
        ;;
    *)
        echo "Sistema desconocido"
        ;;
esac

Los operadores de cortocircuito && y || permiten escribir condiciones de una sola linea cuando la logica es simple:

[[ -d /var/log ]] && echo "Directorio de logs presente"
command -v docker >/dev/null || { echo "Docker no esta instalado" >&2; exit 1; }

Sin embargo, estos patrones no deben sustituir a if/else cuando el bloque verdadero puede fallar, porque el cortocircuito puede producir comportamientos inesperados.

Otra tecnica avanzada consiste en capturar tanto la salida como el estado de un comando:

if output=$(comando_que_puede_fallar); then
    echo "Exito: $output"
else
    echo "Fallo con codigo $?" >&2
fi

Este enfoque mantiene el codigo limpio y permite manejar errores de forma granular.

Ejemplos practicos de uso en scripts reales

Un script de respaldo que verifica espacio en disco antes de continuar ilustra varias tecnicas combinadas:

#!/usr/bin/env bash
set -euo pipefail
umbral=10
disponible=$(df / | awk 'NR==2 {print $4}')
if (( disponible < umbral * 1024 * 1024 )); then
    echo "Espacio insuficiente" >&2
    exit 1
fi
echo "Espacio suficiente, iniciando respaldo"
# comandos de respaldo

Otro ejemplo tipico es un script de despliegue que selecciona la configuracion segun el entorno:

#!/usr/bin/env bash
set -euo pipefail
entorno="${1:-}"
if [[ -z "$entorno" ]]; then
    echo "Uso: $0 <entorno>" >&2
    exit 1
fi
if [[ "$entorno" == "produccion" ]]; then
    config="config.prod.yml"
elif [[ "$entorno" == "staging" ]]; then
    config="config.staging.yml"
else
    echo "Entorno no reconocido: $entorno" >&2
    exit 1
fi
if [[ -f "$config" ]]; then
    echo "Usando $config"
else
    echo "Archivo de configuracion $config no encontrado" >&2
    exit 1
fi

Estos patrones se repiten en cientos de scripts de infraestructura. La claridad de las condiciones y la validacion temprana de argumentos reducen de forma significativa el tiempo dedicado a depuracion.

Errores comunes y como evitarlos

Uno de los errores mas frecuentes consiste en omitir las comillas alrededor de variables dentro de [ ]. Una variable vacia convierte [ $var -eq 5 ] en [ -eq 5 ], lo que produce un mensaje de error. La solucion es entrecomillar siempre o migrar a [[]].

Otro error habitual es usar operadores de cadena para comparar numeros o viceversa. La comparacion [ “$a” > “$b” ] realiza una comparacion lexicografica, no numerica. Para numeros se debe usar (( a > b )) o [ “$a” -gt “$b” ].

La falta de validacion de entrada tambien genera fallos. Si un usuario introduce texto en lugar de un numero y el script intenta una operacion aritmetica, Bash puede abortar o producir resultados incorrectos. La validacion con expresiones regulares o con la funcion declare -i mitiga este riesgo.

Finalmente, olvidar el fi de cierre o colocar then en la misma linea sin punto y coma genera errores de sintaxis. Los editores modernos y herramientas como ShellCheck detectan la mayoria de estos problemas antes de la ejecucion.

Conclusiones

Las sentencias if, elif y else proporcionan el mecanismo esencial de toma de decisiones en scripts Bash. Dominar su sintaxis, los diferentes contextos de prueba y las practicas recomendadas en 2026 permite escribir automatizaciones fiables y mantenibles. Preferir [[]] y (( )), activar el modo estricto, validar entradas y entrecomillar variables son habitos que distinguen un script profesional de uno fragil. Con los ejemplos y patrones presentados en esta guia es posible abordar desde comprobaciones simples de archivos hasta logica compleja de despliegue. La practica constante con casos reales consolida el conocimiento y reduce los errores en entornos de produccion.