🐚 Bash — 1989

⬅️ Atlas · 🗂️ Todas las fichas · 📚 Índice de clases

Bash es, con casi total seguridad, el lenguaje que más veces se ejecuta al día en el mundo: cada arranque de un contenedor, cada canalización de integración continua y cada tarea programada de cualquier servidor Linux pasa por él. Y es también el que menos gente reconoce como un lenguaje de programación — hasta que un guion de cuatrocientas líneas falla en producción.

🎯 Por qué está en este programa

Bash es un primo de la familia históricos / shell (Atlas).

Aporta al programa la composición de procesos por tuberías (clase 161) —la idea de McIlroy de 1964 que sostiene el contrato de las 136 clases de este curso— y el componente de automatización de la clase 171 en su forma más extendida. Y aporta un caso serio de la clase 153: la inyección de comandos y por qué la citación importa.

Año 1989; Bourne shell de 1979; Bash 5.x actual
Autoría Brian Fox para GNU; después Chet Ramey, que lo mantiene desde 1993
Familia Históricos / shell; sucesor del Bourne shell de Stephen Bourne
Paradigma Imperativo, orientado a la composición de procesos
Tipado Todo es texto; con arreglos y enteros como añadidos
Memoria No aplica: el intérprete la gestiona
Ejecución Interpretado, línea a línea
Estado 🟢 Omnipresente en Unix, Linux, macOS, contenedores y CI

📜 Historia

Stephen Bourne escribió el Bourne shell (sh) en los Laboratorios Bell en 1979, sustituyendo al shell de Thompson. Y aportó lo que hoy es el lenguaje: estructuras de control, funciones, variables, sustitución de comandos y redirección.

Su predecesor, el shell de Thompson (1971), había implementado las tuberías que Doug McIlroy había propuesto en un memorando de 1964 con una imagen que se ha citado mil veces:

Deberíamos tener alguna forma de acoplar programas como mangueras de jardín.

Y de ahí salió la filosofía de Unix (clase 161): programas pequeños que hacen una cosa, que leen de la entrada estándar y escriben en la salida estándar, y que se componen.

Bash —Bourne Again SHell, un juego de palabras— lo escribió Brian Fox en 1989 para el proyecto GNU, como reemplazo libre del sh de AT&T, añadiendo lo bueno del C shell y del Korn shell: historial, edición de línea, [[ ]], arreglos.

Se convirtió en el shell por defecto de Linux, y con Linux llegó a todas partes. macOS lo usó hasta 2019, cuando cambió a zsh por la licencia GPLv3 de las versiones nuevas de Bash — un detalle de licencias con consecuencias reales.

Y en 2014 tuvo su momento más incómodo: Shellshock, una vulnerabilidad en el manejo de funciones exportadas por variables de entorno que estuvo presente veinticinco años y afectó a millones de servidores.

🏭 Dónde vive hoy

🧠 Lo que enseña: componer procesos, y las trampas de la citación

Uno, la tubería, que es el contenido de la clase 161:

grep ERROR registro.log | awk '{print $4}' | sort | uniq -c | sort -rn | head

Cinco programas, ninguno de los cuales sabe de los otros, encadenados por texto. Cada uno se escribió por separado, en años distintos, y componen porque todos respetan el contrato: entrada estándar, salida estándar — que es exactamente el contrato de este curso (clase 040).

Dos, y es la parte que hay que aprender bien: la citación (clase 153).

# ✗ TODOS estos están mal
rm $fichero                  # si el nombre tiene espacios, borra varias cosas
if [ $var = "x" ]             # si $var está vacío, error de sintaxis
for f in $(ls *.txt)           # se rompe con espacios y con saltos de línea
eval "comando $entrada"         # inyección de comandos

# ✓ Y así se escriben
rm -- "$fichero"
if [[ "$var" == "x" ]]
for f in *.txt

La regla es simple y casi nadie la sigue: entrecomillar SIEMPRE las variables. Sin comillas, Bash divide por espacios y expande comodines sobre el valor — que es la causa de la mayoría de los guiones que fallan con un nombre de fichero raro, y de bastantes incidentes de seguridad.

Y tres, las tres líneas que deberían encabezar todo guion serio:

#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'

Y la advertencia de la clase 171 aplica aquí más que en ningún sitio: el guion de shell es código de producción. Despliega, borra y mueve datos. Merece control de versiones, revisión (clase 146) y shellcheck — que es un analizador estático excelente y gratuito, y que detecta la mayoría de los errores de esta sección.

🔄 Lo que se ha modernizado

⚙️ Cómo se ejecuta hoy

bash main.sh < entrada.txt          # ejecutar
./main.sh                            # con el shebang y permiso de ejecución

shellcheck main.sh                    # ← análisis estático (clase 146)
shfmt -d main.sh                       # formato
bats pruebas/                           # pruebas (clase 139)

🧪 El programa de la clase 041 en Bash

Esta versión se escribe aquí y no está verificada en CI (clase 040).

#!/usr/bin/env bash
set -euo pipefail

read -r precio cantidad descuento

# Bash NO tiene aritmética de coma flotante: hay que delegar en bc o en awk.
total=$(awk -v p="$precio" -v c="$cantidad" -v d="$descuento" \
            'BEGIN { printf "%.2f", p * c * (1 - d) }')

printf 'Total: %s\n' "$total"

Lo que hay que ver, y es lo más honesto que puede decir esta ficha.

📚 Fuentes y bibliografía


⏮️ Volver al Atlas · 🗂️ Todas las fichas · 🔗 Relacionadas: Perl · Tcl · PowerShell · JCL · Python