El comando test y operadores condicionales en Bash

Introducción

En la administración de sistemas y la automatización de tareas, los scripts Bash son una herramienta esencial. Dentro de estos scripts, la capacidad de tomar decisiones basadas en condiciones es fundamental para crear flujos de lógica que se adapten a diferentes situaciones. El comando test y sus operadores condicionales permiten evaluar expresiones que devuelven un estado de verdad o falsedad, lo que luego se puede usar en estructuras if, while o until.

¿Qué es el comando test?

El comando test es una built‑in de Bash que evalúa una expresión y devuelve un código de salida de cero cuando la expresión es verdadera y distinto de cero cuando es falsa. Su sintaxis básica es:

test EXPRESIÓN

Aunque se puede escribir directamente, es más común ver su forma abreviada con corchetes:

[ EXPRESIÓN ]

Los corchetes son sinónimo de test y deben estar separados por espacios tanto del corchete de apertura como del de cierre.

Operadores de prueba de archivos

Los operadores de archivo permiten inspeccionar el estado de un archivo o directorio. Algunos de los más usados son:

  • -a FILE: verdadero si FILE existe.
  • -b FILE: verdadero si FILE existe y es un bloque especial.
  • -c FILE: verdadero si FILE existe y es un carácter especial.
  • -d FILE: verdadero si FILE existe y es un directorio.
  • -e FILE: verdadero si FILE existe (equivalente a -a).
  • -f FILE: verdadero si FILE existe y es un archivo regular.
  • -g FILE: verdadero si FILE existe y tiene el bit SGID activado.
  • -h FILE o -L FILE: verdadero si FILE existe y es un enlace simbólico.
  • -p FILE: verdadero si FILE existe y es una tubería con nombre (FIFO).
  • -r FILE: verdadero si FILE existe y es legible.
  • -s FILE: verdadero si FILE existe y tiene un tamaño mayor que cero.
  • -t FD: verdadero si el descriptor de archivo FD está abierto y se refiere a una terminal.
  • -u FILE: verdadero si FILE existe y tiene el bit SUID activado.
  • -w FILE: verdadero si FILE existe y es escribible.
  • -x FILE: verdadero si FILE existe y es ejecutable.
  • -O FILE: verdadero si FILE existe y es propiedad del usuario efectivo.
  • -G FILE: verdadero si FILE existe y pertenece al grupo efectivo.
  • -k FILE: verdadero si FILE existe y tiene el bit sticky activado.

Operadores de prueba de cadenas

Para trabajar con texto, Bash ofrece varios operadores que comparan cadenas de caracteres:

  • STRING1 = STRING2: verdadero si las cadenas son idénticas.
  • STRING1 != STRING2: verdadero si las cadenas difieren.
  • -z STRING: verdadero si la longitud de STRING es cero (cadena vacía).
  • -n STRING: verdadero si la longitud de STRING es mayor que cero.
  • STRING: verdadero si STRING no está vacía (equivalente a -n STRING).

Operadores de prueba de enteros

Al comparar valores numéricos se utilizan los siguientes operadores:

  • INT1 -eq INT2: verdadero si INT1 es igual a INT2.
  • INT1 -ne INT2: verdadero si INT1 no es igual a INT2.
  • INT1 -lt INT2: verdadero si INT1 es menor que INT2.
  • INT1 -le INT2: verdadero si INT1 es menor o igual que INT2.
  • INT1 -gt INT2: verdadero si INT1 es mayor que INT2.
  • INT1 -ge INT2: verdadero si INT1 es mayor o igual que INT2.

Operadores lógicos

Para combinar varias pruebas se pueden usar los operadores lógicos:

  • ! EXPRESIÓN: negación, invierte el resultado de la expresión.
  • EXPRESIÓN1 -a EXPRESIÓN2: AND lógico, verdadero si ambas expresiones son verdaderas.
  • EXPRESIÓN1 -o EXPRESIÓN2: OR lógico, verdadero si al menos una expresión es verdadera.

Nota: los operadores -a y -o son específicos del comando test y de los corchetes simples [ ]. En la sintaxis de corchetes dobles [[ ]] se prefieren && y ||.

Uso del test en sentencias if

El patrón más común es combinar test con una estructura condicional:

if test -f "$archivo"; then
    echo "El archivo existe."
else
    echo "El archivo no existe."
fi

Equivalentemente, usando corchetes:

if [ -f "$archivo" ]; then
    echo "El archivo existe."
else
    echo "El archivo no existe."
fi

En ambos casos es importante rodear la variable entre comillas para evitar problemas con espacios o caracteres especiales.

Diferencias entre [ ] y [[ ]]

Aunque los corchetes simples [ ] son sinónimo de test, los corchetes dobles [[ ]] son una palabra clave de Bash que ofrece características adicionales:

  • No requieren que los operadores sean escapados (por ejemplo, [[ $var == *pat* ]] funciona sin necesidad de backslashes).
  • Permiten expresiones regulares con el operador =~.
  • Evitan la división de palabras y la expansión de nombres de archivo dentro de los corchetes.
  • Son más legibles para combinaciones lógicas usando && y ||.

Ejemplo con expresiones regulares:

if [[ "$email" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
    echo "Dirección de correo válida."
else
    echo "Dirección de correo no válida."
fi

Ejemplos prácticos

A continuación se presentan algunos scripts que ilustran el uso de test y sus operadores:

Verificar si un directorio es escribible

#!/bin/bash
DIR="/var/log"
if [ -w "$DIR" ]; then
    echo "El directorio $DIR es escribible."
else
    echo "El directorio $DIR NO es escribible."
fi

Comprobar si dos variables numéricas son iguales

#!/bin/bash
A=15
B=20
if [ "$A" -eq "$B" ]; then
    echo "A y B son iguales."
else
    echo "A y B son diferentes."
fi

Validar que un parámetro no esté vacío

#!/bin/bash
if [ -z "$1" ]; then
    echo "Error: se requiere un argumento."
    exit 1
else
    echo "Argumento recibido: $1"
fi

Usar AND y OR en una sola prueba

#!/bin/bash
if [ -f "$archivo" -a -r "$archivo" ]; then
    echo "El archivo existe y es legible."
else
    echo "Falta el archivo o no tiene permisos de lectura."
fi

Trampas comunes y buenas prácticas

  • Siempre colocar espacios alrededor de los operadores y dentro de los corchetes: [ $var -eq 5 ] es correcto; [$var-eq5] fallará.
  • Proteger las variables con comillas dobles para evitar división de palabras y expansión de globs.
  • Preferir [[ ]] cuando se necesite patrones o expresiones regulares, ya que es más seguro y legible.
  • Recuerde que el operador de asignación = dentro de [ ] es para comparación de cadenas, no para asignación.
  • En contextos donde se necesite invertir una prueba, use ! antes de la expresión o el operador -not (aunque este último no es estándar en todas las versiones).

Conclusión

El comando test y sus operadores condicionales son la base de la toma de decisiones en Bash. Dominar su sintaxis, conocer los distintos tipos de pruebas (archivo, cadena, entero) y saber cómo combinarlos con operadores lógicos permite escribir scripts más robustos, legibles y mantenibles. Ya sea que esté verificando la existencia de un archivo, validando la entrada del usuario o creando flujos de trabajo complejos, el uso adecuado de test hará que sus scripts sean más confiables y profesionales.