⏱️ Lectura: 10 min

Un colon no hace nada. Literalmente: es un comando que evalúa sus argumentos y tira el resultado a la basura. Y sin embargo, ese mismo colon lleva 55 años escondido en scripts de shell resolviendo problemas que la mayoría de los desarrolladores resuelve con cuatro o cinco líneas de más.

📑 En este artículo
  1. TL;DR
  2. Introducción
  3. Qué pasó
  4. Contexto e historia
  5. Detalles técnicos y rendimiento
  6. Cómo empezar a probarlo
  7. Impacto y análisis
  8. Qué sigue
  9. Preguntas frecuentes
    1. ¿Por qué necesito el colon si la expansión ocurre igual sin él?
    2. ¿En qué se diferencia de VAR=${VAR:-default}?
    3. ¿Funciona en todos los shells POSIX?
    4. ¿Perjudica la legibilidad del script?
    5. ¿De dónde viene el nombre comando nulo?
    6. ¿Sirve en scripts de CI/CD?
  10. Referencias

El programador Filip Roséen lo documentó en un artículo publicado el 23 de julio de 2026 en su sitio refp.se, modificado el 26 de julio de 2026, donde repasa por qué el llamado comando nulo (:) sigue siendo, medio siglo después, uno de los trucos menos conocidos y más útiles de bash y POSIX shell.

TL;DR

  • Filip Roséen publicó el 23 de julio de 2026 en refp.se un artículo sobre el colon nulo en shell, actualizado el 26 de julio de 2026.
  • El comando : no ejecuta nada: solo evalúa sus argumentos y descarta el resultado.
  • : “${1:?falta un argumento}” reemplaza un bloque if de 4 líneas por una sola línea para validar parámetros obligatorios.
  • El origen del colon nulo se remonta a 1971, en el shell de Thompson, donde también servía de etiqueta y primer marcador de comentarios de Unix.
  • : “${VAR:=valor}” asigna un valor por defecto sin que el shell intente ejecutar ese valor como comando.
  • El patrón : > archivo.log trunca un archivo sin necesitar truncate ni echo -n.
  • trap : INT permite ignorar una señal sin definir una función de manejo aparte.

Introducción

Para cualquier desarrollador en LATAM que mantenga pipelines de CI/CD, entrypoints de Docker o scripts de deploy, el shell POSIX sigue siendo el pegamento invisible de la infraestructura. El colon nulo en shell es exactamente ese tipo de detalle que nadie enseña en un bootcamp pero que aparece constantemente en repositorios de código abierto serios: Kubernetes, Alpine, los propios scripts de instalación de Homebrew o nvm lo usan.

Roséen no descubrió el comando (existe desde antes que la mayoría de los lenguajes de programación actuales), pero su artículo funciona como un recordatorio de que las herramientas más viejas de Unix todavía resuelven problemas modernos con menos código que un framework.

Qué pasó

El artículo original nace de un caso concreto: reemplazar una validación de argumento típica, un if de cuatro líneas que comprueba si $1 está vacío, imprime un error y hace exit 1, por una sola línea usando parámetro-expansión con el colon nulo como prefijo.

código de shell mostrando el colon nulo validando un argumento
El diagnóstico incluye el nombre de la variable, no solo un mensaje genérico. Foto de Natalia Gasiorowska en Unsplash

La gracia técnica es que ${1:?mensaje} ya comprueba si el parámetro está vacío o sin definir, y si falta, imprime el mensaje en stderr y termina el script con código distinto de cero. El colon al principio de la línea es lo que evita que el shell intente ejecutar el resultado de esa expansión como si fuera un comando.

#!/bin/sh
: "${NOMBRE:?falta indicar un nombre}"
echo "Hola, $NOMBRE"

Al correr sh saludo.sh sin variable, el shell responde saludo.sh: line 2: NOMBRE: falta indicar un nombre y sale con estado distinto de cero. Con NOMBRE=ana sh saludo.sh, el script imprime Hola, ana con normalidad.

Contexto e historia

El comando : no es un invento de bash ni de POSIX: aparece ya en el shell de Thompson de 1971, la primera shell de Unix, donde cumplía doble función: servía como etiqueta para saltos y, antes de que existiera una sintaxis dedicada de comentarios, como el primer marcador de comentario del sistema.

POSIX heredó ese comportamiento y lo formalizó como null utility: un comando que siempre retorna éxito, no produce efectos y sirve como relleno sintáctico allí donde el lenguaje exige un comando pero el programador no necesita ejecutar nada, por ejemplo dentro de la rama else vacía de un if.

💭 Clave: el colon nulo y el comando true hacen básicamente lo mismo (no hacer nada y salir con éxito), pero : es un built-in del propio shell, mientras que en algunos sistemas true puede ser un binario externo. Eso hace que : sea marginalmente más rápido en scripts que lo invocan miles de veces.

Detalles técnicos y rendimiento

La clave para entender el truco está en separar dos cosas que ocurren en la misma línea. Primero, la expansión de parámetros definida en el manual de bash: sucede siempre, tenga o no un comando delante. Segundo, qué hace el shell con el resultado de esa expansión.

Si escribís ${HELLO:=123} como línea completa, sin nada delante, el shell expande la variable, la deja en 123 y después intenta ejecutar 123 como si fuera el nombre de un programa. El resultado es un error de tipo command not found. Si en cambio prefijás la expansión con el colon nulo, el shell evalúa la expansión (con su efecto secundario de asignar HELLO=123) y luego ejecuta :, que descarta silenciosamente ese valor como argumento sin intentar correrlo.

PatrónQué haceEjemploCuándo usarlo
: "${VAR:?msg}"Exige que la variable existavalidar un argumento obligatorioscripts con parámetros requeridos
: "${VAR:=valor}"Asigna un valor por defectoconfiguración opcionalflags con un default razonable
: > archivoTrunca o crea un archivo vacíoreiniciar un logrotar logs sin borrar el archivo
trap : SEÑALIgnora una señal sin acciónmanejo de interrupcionespermitir que un sleep sea interrumpible sin abortar el script

Cómo empezar a probarlo

No hay nada que instalar: el colon nulo es parte de cualquier shell compatible con POSIX. Podés probarlo hoy mismo en los tres sistemas operativos principales.

  • Linux: cualquier terminal con bash, dash o sh ya lo soporta, incluidas las imágenes mínimas de Alpine que usan ash de BusyBox.
  • macOS: la Terminal trae zsh por defecto desde Catalina, y el colon nulo funciona igual que en bash.
  • Windows: no existe en cmd.exe ni en PowerShell nativo (ahí el equivalente es el operador # como no-op o $null), pero funciona sin cambios dentro de Git Bash o de una distro de WSL con bash/dash instalado.

Un script realista de deploy que combina las dos variantes principales, argumento obligatorio y valor por defecto, se ve así:

#!/bin/sh
: "${DEPLOY_ENV:?debes definir DEPLOY_ENV (staging|production)}"
: "${DOCKER_REGISTRY:=registry.miempresa.com}"
: "${MAX_RETRIES:=3}"

echo "Desplegando en $DEPLOY_ENV usando $DOCKER_REGISTRY (reintentos: $MAX_RETRIES)"

Corriendo DEPLOY_ENV=staging sh deploy.sh obtenés Desplegando en staging usando registry.miempresa.com (reintentos: 3). Si omitís DEPLOY_ENV, el script aborta antes de llegar al echo, con el nombre exacto de la variable que falta en el mensaje de error.

diagrama de flujo del comando colon nulo verificando una variable de entorno
El script aborta antes del echo si DEPLOY_ENV no está definida. Foto de Joshua J. Cotten en Unsplash

Para confirmar que el patrón funciona en tu shell específico, basta con correr : "${TEST_VAR:=ok}"; echo $TEST_VAR en la terminal: si imprime ok, el comportamiento es el esperado.

flowchart TD
 A["Inicio del script"] --> B{"Variable definida?"}
 B -- "Si" --> C["Continua ejecucion normal"]
 B -- "No" --> D["Imprime mensaje en stderr"]
 D --> E["Sale con codigo distinto de cero"]

Impacto y análisis

El beneficio concreto no es solo ahorrar líneas: es reducir la superficie de error. Con VAR=${VAR:-default}, el nombre de la variable aparece dos veces en la misma línea, y un typo en cualquiera de las dos apariciones (DATA_DIR contra DATA_DRI, por ejemplo) produce un bug silencioso donde la variable original queda vacía y el default nunca se aplica. Con : "${DATA_DIR:=/var/data}", el nombre aparece una sola vez.

💡 Tip: si tu script usa set -u para fallar ante variables sin definir, podés validar varias de una sola vez con : "$VAR_A" "$VAR_B" "$VAR_C": si alguna no existe, set -u aborta el script ahí mismo.

El costo real es la legibilidad para quien no conoce el idioma. Un desarrollador que nunca vio : "${1:?...}" puede tardar minutos en entender qué hace esa línea, mientras que un if [ -z "$1" ]; then ... fi se lee de corrido incluso sin experiencia previa en shell.

⚠️ Ojo: en equipos con rotación alta o con desarrolladores junior, vale la pena acompañar el patrón con un comentario corto la primera vez que aparece en el repositorio, o documentarlo en la guía de estilo interna.

Qué sigue

Roséen mantiene una sección de preguntas frecuentes que promete actualizar a medida que surgen dudas de lectores, lo que sugiere que el artículo seguirá creciendo. Para equipos que ya usan shellcheck en CI, vale la pena considerar si estos patrones deberían entrar en la guía de estilo interna, dado que son 100% POSIX y funcionan igual en dash, ash (BusyBox), bash, zsh y ksh, algo relevante para imágenes Docker que priorizan tamaño y usan shells mínimos.

Preguntas frecuentes

¿Por qué necesito el colon si la expansión ocurre igual sin él?

Porque sin un comando delante, el shell interpreta el resultado de la expansión como el nombre de un programa a ejecutar, y si ese valor no es un comando válido, falla con command not found. El colon nulo evalúa la expansión y descarta el resultado sin intentar correrlo.

¿En qué se diferencia de VAR=${VAR:-default}?

Es en gran parte preferencia personal, pero : "${VAR:=default}" menciona el nombre de la variable una sola vez, reduciendo a la mitad los lugares donde puede colarse un typo.

¿Funciona en todos los shells POSIX?

Sí, el comando nulo es parte del estándar POSIX shell command language y funciona igual en dash, ash de BusyBox, bash, zsh y ksh.

¿Perjudica la legibilidad del script?

Puede, sobre todo para quien no conoce el idioma. Se recomienda comentarlo la primera vez que aparece en un repositorio compartido.

¿De dónde viene el nombre comando nulo?

Del shell de Thompson de 1971, donde : ya existía y doblaba como etiqueta de salto y como el primer marcador de comentarios de Unix.

¿Sirve en scripts de CI/CD?

Sí: es exactamente el tipo de validación que conviene poner al inicio de un entrypoint de Docker o de un job de pipeline, para fallar rápido si falta una variable de entorno crítica.

📖 Resumen en Telegram: Ver resumen

Probalo vos: abrí una terminal ahora mismo y corré : "${TEST_VAR:=ok}"; echo $TEST_VAR para ver el patrón funcionando en tu propio shell.

Referencias

📱 ¿Te gusta este contenido? Únete a nuestro canal de Telegram @programacion donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.

Imagen destacada: Foto de RoonZ nl en Unsplash


Andrés Morales

Desarrollador e investigador en inteligencia artificial. Escribe sobre modelos de lenguaje, frameworks, herramientas para devs y lanzamientos open source. Cubre papers de ML, ecosistema de startups tech y tendencias de programación.

0 Comentarios

Deja un comentario

Marcador de posición del avatar

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.