Agregar colores a los scripts de Bash
Guía completa para una terminal más expresiva

Cualquiera que haya trabajado con pipelines de CI/CD o scripts de automatización sabe lo frustrante que es leer un muro de texto blanco sobre negro tratando de encontrar dónde algo salió mal. Esto me llevó a explorar a fondo la coloración de salida en Bash, y lo que encontré fue sorprendentemente simple y poderoso.
En esta entrada vamos a cubrir todo lo que necesitas saber para darle vida a tus scripts con color: desde los fundamentos de los códigos ANSI hasta patrones avanzados que puedes reutilizar en tus proyectos.
¿Por qué colorear la salida de tus scripts?
Antes de entrar en el código, vale la pena reflexionar sobre por qué esto importa. Cuando ejecutas un script que despliega infraestructura, corre pruebas o gestiona contenedores, la cantidad de output puede ser abrumadora. Los colores te permiten:
Identificar errores al instante: rojo para fallos, verde para éxito.
Separar secciones lógicas: cada fase de tu pipeline puede tener su propio color.
Mejorar la experiencia del usuario: si otros desarrolladores usan tus scripts, agradecerán la claridad visual.
Reducir el tiempo de depuración: encontrar el problema en un log colorizado es exponencialmente más rápido.
En el contexto de DevOps, donde la automatización es el pan de cada día, esto no es un lujo — es productividad real.
Los códigos de escape ANSI: la base de todo
La magia detrás de los colores en la terminal son los códigos de escape ANSI. El estándar ANSI (American National Standards Institute) define una serie de secuencias de caracteres que las terminales interpretan como instrucciones de formato en lugar de texto visible.
La estructura básica de una secuencia de escape es:
\e[CODIGOm
Donde:
\e(o\033en octal, o\x1ben hexadecimal) inicia la secuencia de escape.[abre la secuencia CSI (Control Sequence Introducer).CODIGOes el número que define el color o estilo.mcierra la secuencia.
Tabla de colores de primer plano (texto)
Color | Código de primer plano | Código de fondo |
|---|---|---|
Negro | 30 | 40 |
Rojo | 31 | 41 |
Verde | 32 | 42 |
Amarillo | 33 | 43 |
Azul | 34 | 44 |
Magenta | 35 | 45 |
Cian | 36 | 46 |
Gris claro | 37 | 47 |
Gris oscuro | 90 | 100 |
Rojo claro | 91 | 101 |
Verde claro | 92 | 102 |
Amarillo claro | 93 | 103 |
Azul claro | 94 | 104 |
Magenta claro | 95 | 105 |
Cian claro | 96 | 106 |
Blanco | 97 | 107 |
Códigos de estilo (no relacionados con color)
Código | Descripción |
|---|---|
0 | Restablecer/Normal |
1 | Texto en negrita |
2 | Texto tenue |
3 | Texto en cursiva |
4 | Texto subrayado |
5 | Texto parpadeante |
7 | Invertir colores |
8 | Texto oculto |
9 | Texto tachado |
Tu primer texto en color
El comando echo imprime texto en la terminal. Para que interprete las secuencias de escape ANSI, necesitamos la opción -e:
echo -e "\e[31mTexto en rojo\e[0m"
Desglosemos esto:
\e[31m→ Activa el color rojo (código 31 de primer plano).Texto en rojo→ El contenido que se mostrará en rojo.\e[0m→ Restablece el formato a la normalidad (código 0).
⚠️ Importante: El
\e[0mal final es crucial. Sin él, todo el texto que imprimas después en esa sesión de terminal aparecerá en rojo. Siempre cierra tus secuencias de color.
Usando variables para mayor legibilidad
Escribir \e[31m cada vez que quieres rojo no es práctico ni legible. La solución es almacenar los códigos en variables:
RED="\e[31m"
GREEN="\e[32m"
YELLOW="\e[33m"
BLUE="\e[34m"
MAGENTA="\e[35m"
CYAN="\e[36m"
ENDCOLOR="\e[0m"
echo -e "\({RED}Error: algo salió mal\){ENDCOLOR}"
echo -e "\({GREEN}Éxito: despliegue completado\){ENDCOLOR}"
echo -e "\({YELLOW}Advertencia: revisa la configuración\){ENDCOLOR}"
Ahora el código es mucho más expresivo. Cualquiera que lo lea entiende inmediatamente la intención.
Script básico completo
#! /usr/bin/env bash
RED="\e[31m"
GREEN="\e[32m"
ENDCOLOR="\e[0m"
echo -e "\({RED}This is some red text, \){ENDCOLOR}"
echo -e "\({GREEN}And this is some green text\){ENDCOLOR}"
Combinando estilos y colores
Aquí es donde la cosa se pone interesante. Puedes combinar múltiples códigos separándolos con punto y coma (;) dentro de una sola secuencia de escape:
\e[ESTILO;COLORm
Por ejemplo:
#! /usr/bin/env bash
RED="31"
GREEN="32"
BOLDGREEN="\e[1;${GREEN}m"
ITALICRED="\e[3;${RED}m"
ENDCOLOR="\e[0m"
echo -e "\({BOLDGREEN}Behold! Bold, green text.\){ENDCOLOR}"
echo -e "\({ITALICRED}Italian italics\){ENDCOLOR}"
Observa cómo separamos el código de estilo del código de color: 1;32 significa "negrita + verde". Puedes incluso combinar tres o más códigos: \e[1;4;31m te daría texto rojo, negrita y subrayado.
Más combinaciones útiles
BOLD="\e[1m"
DIM="\e[2m"
UNDERLINE="\e[4m"
BLINK="\e[5m"
REVERSE="\e[7m"
STRIKETHROUGH="\e[9m"
BOLD_RED="\e[1;31m"
UNDERLINE_BLUE="\e[4;34m"
BOLD_YELLOW_ON_RED="\e[1;33;41m" # Texto amarillo negrita sobre fondo rojo
Color de fondo
Los códigos de fondo (40-47 y 100-107) se usan de la misma forma. Puedes combinarlos con colores de texto:
# Texto blanco sobre fondo rojo (ideal para errores críticos)
echo -e "\e[97;41m CRITICAL ERROR \e[0m Something broke badly"
# Texto negro sobre fondo amarillo (ideal para advertencias)
echo -e "\e[30;43m WARNING \e[0m Check your configuration"
# Texto negro sobre fondo verde (ideal para éxito)
echo -e "\e[30;42m SUCCESS \e[0m Deployment completed"
Este patrón de "badges" o etiquetas de color es muy común en herramientas CLI profesionales.
Colores de 256 colores y RGB (True Color)
Las terminales modernas soportan más que los 16 colores básicos ANSI.
256 colores
Puedes acceder a una paleta de 256 colores usando:
# Primer plano: \e[38;5;COLORm
# Fondo: \e[48;5;COLORm
echo -e "\e[38;5;208mTexto naranja (color 208)\e[0m"
echo -e "\e[48;5;27mFondo azul intenso\e[0m"
Los valores van de 0 a 255, donde 0-7 son los colores estándar, 8-15 son los colores brillantes, 16-231 es un cubo de color 6×6×6, y 232-255 son tonos de gris.
True Color (24-bit RGB)
Si tu terminal lo soporta (la mayoría de las modernas lo hacen), puedes usar colores RGB exactos:
# Primer plano: \e[38;2;R;G;Bm
# Fondo: \e[48;2;R;G;Bm
echo -e "\e[38;2;255;100;0mNaranja personalizado\e[0m"
echo -e "\e[38;2;0;200;255mAzul cielo\e[0m"
Esto te da acceso a más de 16 millones de colores.
Alternativas a \e: compatibilidad entre terminales
Aunque \e funciona en la mayoría de las terminales modernas, existen alternativas más portables:
Secuencia | Descripción |
|---|---|
| Funciona en la mayoría de terminales modernas |
| Notación octal, más portable |
| Notación hexadecimal |
| Sintaxis ANSI-C quoting de Bash |
Si necesitas máxima compatibilidad, usa \033:
RED="\033[31m"
ENDCOLOR="\033[0m"
echo -e "\({RED}Compatible con más terminales\){ENDCOLOR}"
O usa el comando tput, que consulta la base de datos terminfo de tu sistema:
RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
BOLD=$(tput bold)
RESET=$(tput sgr0)
echo "\({RED}Rojo con tput\){RESET}"
echo "\({BOLD}\){GREEN}Verde negrita${RESET}"
La ventaja de tput es que genera la secuencia correcta para cada terminal automáticamente.
Patrón práctico: funciones de logging con color
En lugar de usar variables sueltas, un patrón más profesional es crear funciones de logging reutilizables:
#! /usr/bin/env bash
# --- Colores ---
RED="\e[31m"
GREEN="\e[32m"
YELLOW="\e[33m"
BLUE="\e[34m"
BOLD="\e[1m"
DIM="\e[2m"
ENDCOLOR="\e[0m"
# --- Funciones de logging ---
log_info() {
echo -e "\({BLUE}[INFO]\){ENDCOLOR} $1"
}
log_success() {
echo -e "\({GREEN}[OK]\){ENDCOLOR} $1"
}
log_warning() {
echo -e "\({YELLOW}[WARN]\){ENDCOLOR} $1"
}
log_error() {
echo -e "\({RED}[ERROR]\){ENDCOLOR} $1"
}
log_step() {
echo -e "\({BOLD}\){BLUE}==>\({ENDCOLOR}\){BOLD} \(1\){ENDCOLOR}"
}
# --- Uso ---
log_step "Iniciando despliegue..."
log_info "Conectando al cluster de Kubernetes..."
log_success "Conexión establecida"
log_warning "La imagen no tiene tag específico, usando :latest"
log_error "Fallo al aplicar el manifiesto: timeout después de 30s"
Este patrón es extremadamente útil para scripts de CI/CD, hooks de Git y herramientas de automatización.
Detectando soporte de color
No todas las terminales soportan colores (piensa en logs redirigidos a archivos o terminales mínimas). Es buena práctica verificar:
#! /usr/bin/env bash
# Desactivar colores si no estamos en una terminal interactiva
if [[ -t 1 ]]; then
RED="\e[31m"
GREEN="\e[32m"
YELLOW="\e[33m"
ENDCOLOR="\e[0m"
else
RED=""
GREEN=""
YELLOW=""
ENDCOLOR=""
fi
echo -e "\({GREEN}Esto se ve verde en terminal, y normal en un archivo\){ENDCOLOR}"
El test -t 1 verifica si el file descriptor 1 (stdout) está conectado a una terminal. Si el output se redirige a un archivo (script.sh > log.txt), los códigos de color se omiten, evitando ensuciar los logs con caracteres de escape ilegibles.
También puedes respetar la variable de entorno NO_COLOR (estándar de la comunidad: no-color.org):
if [[ -n "${NO_COLOR:-}" ]]; then
RED=""
GREEN=""
ENDCOLOR=""
fi
Ejemplo completo: script de despliegue con salida colorizada
Para cerrar, aquí tienes un ejemplo más realista que podrías adaptar para tus propios scripts de despliegue o hooks de Git:
#! /usr/bin/env bash
set -euo pipefail
# ============================================================
# Colores y estilos
# ============================================================
if [[ -t 1 ]]; then
RED="\e[31m"
GREEN="\e[32m"
YELLOW="\e[33m"
BLUE="\e[34m"
CYAN="\e[36m"
BOLD="\e[1m"
DIM="\e[2m"
NC="\e[0m" # No Color
else
RED="" GREEN="" YELLOW="" BLUE="" CYAN="" BOLD="" DIM="" NC=""
fi
# ============================================================
# Funciones de utilidad
# ============================================================
header() {
echo ""
echo -e "\({BOLD}\){CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "\({BOLD}\){CYAN} \(1\){NC}"
echo -e "\({BOLD}\){CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
}
info() { echo -e " \({BLUE}ℹ\){NC} $1"; }
success() { echo -e " \({GREEN}✔\){NC} $1"; }
warn() { echo -e " \({YELLOW}⚠\){NC} $1"; }
error() { echo -e " \({RED}✘\){NC} $1"; }
step() { echo -e " \({DIM}→\){NC} $1"; }
# ============================================================
# Script principal
# ============================================================
header "DEPLOY v2.4.1 → production"
info "Verificando pre-requisitos..."
step "kubectl configurado: $(kubectl config current-context 2>/dev/null || echo 'N/A')"
step "Docker version: $(docker --version 2>/dev/null | cut -d' ' -f3 || echo 'N/A')"
success "Pre-requisitos verificados"
info "Construyendo imagen Docker..."
if docker build -t myapp:v2.4.1 . > /dev/null 2>&1; then
success "Imagen construida exitosamente"
else
error "Fallo al construir la imagen"
exit 1
fi
info "Aplicando manifiestos de Kubernetes..."
warn "Usando namespace: production (¡cuidado!)"
success "Despliegue completado"
header "RESUMEN"
echo -e " Estado: \({GREEN}\){BOLD}EXITOSO${NC}"
echo -e " Versión: \({CYAN}v2.4.1\){NC}"
echo -e " Tiempo: \({DIM}12.4s\){NC}"
echo ""
Consejos finales
Siempre resetea con
\e[0mal final de cada línea coloreada. No hacerlo es la fuente número uno de bugs visuales.Usa funciones, no variables sueltas en scripts de producción. Son más mantenibles y puedes agregar timestamps, redirección a archivo, y otras mejoras en un solo lugar.
Respeta
NO_COLORy-t 1. Tus scripts serán ciudadanos de primera clase en pipelines automatizados.No abuses del color. Si todo es colorido, nada destaca. Usa rojo solo para errores reales, amarillo para advertencias, y verde para confirmaciones de éxito.
printfvsecho -e: Si buscas portabilidad máxima,printfmaneja secuencias de escape sin necesidad de flags adicionales:printf "\({RED}Error: %s\){ENDCOLOR}\n" "algo falló"Prueba en múltiples terminales. Lo que se ve perfecto en tu iTerm2 o Alacritty puede verse diferente en una terminal más básica.
Las combinaciones son infinitas y son tuyas. Ahora que tienes las herramientas, dale personalidad a tus scripts y haz que la terminal sea un lugar más amigable para trabajar.





