test, [, and [[ (2020)

Los programadores de shell sopesan los compromisos entre el estándar POSIX `[ / test` y `[[` específico de Bash para condicionales, destacando cómo las reglas de sintaxis sutiles, las trampas de las comillas y las rarezas de la lógica booleana pueden introducir errores fácilmente. Muchos abogan por ceñirse a `sh` portátil y compatible con Bourne cuando los scripts deben ejecutarse en sistemas diversos o restringidos (por ejemplo, BSD, sistemas embebidos, imágenes Docker mínimas), mientras que otros prefieren las características de Bash, zsh o ksh por comodidad en entornos controlados. La conversación se amplía hacia si los scripts de shell complejos deberían reemplazarse por lenguajes “reales” como Python o Perl, el papel de herramientas como ShellCheck y `set -euo pipefail`, y cómo equilibrar la portabilidad a largo plazo con la productividad del desarrollador.

Elección de shell y portabilidad

  • Gran división entre “usa Bash/[[ y listo” y “apunta a POSIX sh”.
  • Lado pro-Bash: [[ es más claro y potente; muchos entornos que controlan tienen bash, zsh o ksh de todos modos. Instalar bash se ve como de poco esfuerzo en muchos contextos.
  • Lado de la portabilidad: bash no siempre está presente (BSD, sistemas embebidos, imágenes Docker mínimas, configuraciones solo con busybox, máquinas de clientes bloqueadas, macOS con bash antiguo).
  • Escribir Bourne/POSIX sh se describe como parte de la madurez profesional cuando los scripts se ejecutan en sistemas desconocidos o heredados.
  • Algunos sostienen que la portabilidad tiene un costo y no debería ser un objetivo universal; para scripts internos está bien apoyarse en bashisms.

[, test, y [[

  • [, test son POSIX y suelen ser binarios o builtins; [[ es específico del shell (bash, zsh, ksh, etc.).
  • Varios prefieren test sobre [ para reforzar que es un comando, no sintaxis; la ] de cierre de [ y la “sintaxis” parecida se ven como trucos engañosos.
  • Otros dicen que [[ es preferible cuando ya has apostado por Bash, por su semántica más segura (por ejemplo, regex, coincidencia de patrones, menos problemas de comillas).
  • Algunos insisten en usar solo características POSIX incluso cuando los shells soportan [[; otros dicen que eso es una adoración innecesaria de la portabilidad.

Errores comunes y técnicas

  • La mayor trampa: variables sin comillas con test/[ (valores vacíos o con espacios, comportamiento de un solo argumento). Consejo repetido: “cita tus variables” y usa herramientas como ShellCheck y set -euo pipefail.
  • Usar && / || como abreviatura de if es popular, pero tiene semánticas de fallo diferentes cuando falla el comando después de &&.
  • -a / -o dentro de test se señalan como obsoletos; se prefiere encadenar pruebas separadas con && / ||.
  • La lógica booleana es incómoda: no hay un tipo booleano real; las soluciones usan códigos de salida o 0/1 numéricos.

Cuándo usar shell frente a otro lenguaje

  • Varios sostienen que la lógica compleja debería pasar a un lenguaje “real” (Python, Perl, Node/zx, etc.); shell es mejor para pegamento, orquestación y pruebas de integración.
  • Otros defienden shell como un lenguaje “real” si se usa con disciplina, pero aun así no empezarían proyectos grandes en él.

Estándares, GNUismos y rarezas del ecosistema

  • Debate sobre ceñirse a POSIX frente a explotar extensiones GNU/Bash (pipefail, banderas GNU grep/sed, etc.).
  • POSIX se ve como valioso para la interoperabilidad, pero también como rezagado respecto a las necesidades del mundo real.
  • Varias notas laterales: dash como /bin/sh en Debian/Ubuntu, macOS BSD frente a herramientas GNU, el trato especial de autoconf a [], comportamientos extraños de $_, y disposiciones de busybox con symlink frente a hardlink.