# Bash scripting desde cero

**Categoría:** Linux y sistemas · **Nivel:** Intermedio · **Lectura:** 12 min
**Publicada:** 2026-07-28 · **Actualizada:** 2026-07-28 · **Autoría:** Underc0de
**Versión HTML (canónica):** https://underc0de.org/guias/linux/bash-scripting-desde-cero/

## Respuesta rápida

Un **script de Bash** es un archivo de texto con una **lista de comandos** que la terminal ejecuta en orden, como si los escribieras uno tras otro, pero de forma automática y repetible. Sirve para **automatizar tareas**: copias de seguridad, despliegues, limpiezas, procesamiento de archivos —cualquier cosa que harías a mano varias veces—. Un script empieza con una línea especial llamada **shebang** (#!/usr/bin/env bash) que indica con qué intérprete correrlo; se le da permiso de [ejecución](../permisos-y-propietarios-de-archivos-en-linux/index.md) con chmod +x, y se lanza con ./script.sh. Los elementos básicos son pocos: **variables** (nombre="ana", se usan con $nombre), **argumentos** ($1, $2… lo que se pasa al ejecutarlo), **condicionales** (if), **bucles** (for, while) y **funciones**. La regla de oro para que un script no rompa cosas es empezarlo con set -euo pipefail (que lo detiene ante errores en vez de seguir a ciegas), **entrecomillar las variables** ("$var") y probarlo con cuidado. Herramientas como **ShellCheck** detectan los errores clásicos antes de que causen daño.

## Qué es un script

Cada vez que escribís comandos en la terminal, estás hablando con un **intérprete de comandos** (una *shell*); en Linux, el más común es **Bash**. Un **script** no es más que esos mismos comandos guardados en un archivo, para poder ejecutarlos todos juntos cuando quieras, sin volver a teclearlos.

> **De teclear a automatizar**
>
> Si una tarea consiste en tres o cuatro comandos que repetís a menudo —comprimir una carpeta, moverla, borrar temporales—, meterlos en un script convierte ese procedimiento en **una sola orden**, fiable y siempre igual. Ese es el salto: de hacer las cosas a mano (y con el riesgo de olvidar un paso) a tener un **procedimiento reproducible**.

## Tu primer script

Un primer script, comentado, se ve así:

```text
#!/usr/bin/env bash
# saludo.sh — un primer ejemplo
set -euo pipefail

nombre="$1"              # primer argumento pasado al script
echo "Hola, $nombre"
echo "Hoy hay $(ls | wc -l) elementos en esta carpeta"
```

Para ejecutarlo:

```text
chmod +x saludo.sh     # darle permiso de ejecución (una sola vez)
./saludo.sh Ana        # ejecutarlo pasando "Ana" como argumento $1

# Alternativa sin chmod: pasarlo al intérprete
bash saludo.sh Ana
```

El ./ delante indica que el script está en la carpeta actual (Bash no busca ahí por defecto, por seguridad).

## Los elementos básicos

Con unos pocos elementos se cubre casi todo:

```text
# Variables (¡sin espacios alrededor del =!)
carpeta="/var/log"

# Condicional: hacer algo solo si se cumple una condición
if [[ -d "$carpeta" ]]; then
  echo "La carpeta existe"
else
  echo "No existe" >&2   # mensaje de error a la salida de error
fi

# Bucle for: repetir sobre una lista
for archivo in *.txt; do
  echo "Procesando $archivo"
done

# Bucle while: repetir mientras se cumpla una condición
contador=0
while [[ $contador -lt 3 ]]; do
  echo "vuelta $contador"
  contador=$((contador + 1))
done

# Función: agrupar y reutilizar
saludar() {
  echo "Hola, $1"
}
saludar "mundo"
```

Combinados con [tuberías y redirecciones](../redirecciones-y-tuberias-en-la-terminal/index.md), estos elementos permiten encadenar comandos y procesar su salida, que es donde los scripts se vuelven realmente potentes.

## Buenas prácticas

> **Atención**
>
> **set -euo pipefail** al principio: -e detiene el script si un comando falla; -u lo detiene si usás una variable no definida (un típico error de tipeo); -o pipefail hace que una tubería falle si falla cualquier parte, no solo la última. Sin esto, un script sigue adelante tras un error y puede hacer estragos —el ejemplo clásico es un rm -rf "$dir/" donde $dir quedó vacío—.

- **Entrecomillar siempre las variables:** "$var", no $var. Evita que espacios o caracteres raros rompan el comando.
- **Empezar con set -euo pipefail.** Convierte fallos silenciosos en detenciones seguras.
- **Pasar el script por [ShellCheck](https://www.shellcheck.net/).** Detecta los errores clásicos automáticamente.
- **Comentar qué hace y qué espera.** El «yo» de dentro de seis meses lo agradece.
- **Probar en seco.** Antes de un script destructivo, imprimir lo que *haría* (con echo) en vez de hacerlo.

## Errores frecuentes

- **Poner espacios alrededor del =.** nombre = "ana" falla; debe ser nombre="ana".
- **No entrecomillar variables.** Un valor con espacios se parte en varios argumentos; usar "$var".
- **Omitir set -euo pipefail.** El script sigue tras un error y puede causar daño.
- **Un rm -rf con variable vacía.** Si la ruta queda vacía, borra algo inesperado; validar antes.
- **Confiar en el directorio actual.** Un script que asume dónde se ejecuta falla al moverlo; usar rutas explícitas.
- **No dar permiso de ejecución.** Sin chmod +x, ./script.sh da «permiso denegado».
- **Reinventar lo complejo en Bash.** Para lógica pesada o datos estructurados, a veces conviene Python; Bash brilla en pegar comandos.

## Preguntas frecuentes

**¿Qué es un script de Bash y para qué sirve?**
Un script de Bash es un archivo de texto que contiene una secuencia de comandos que el intérprete de comandos de Linux ejecuta en orden, de forma automática, tal como se ejecutarían si se escribieran uno a uno en la terminal. Bash es el intérprete de comandos más habitual en los sistemas Linux, y un script no es más que la forma de guardar en un archivo esos comandos para poder ejecutarlos todos juntos cuando se desee, sin necesidad de teclearlos de nuevo cada vez. Su utilidad principal es la automatización de tareas, especialmente aquellas que son repetitivas, tediosas o propensas a errores cuando se hacen a mano. Ejemplos típicos son realizar copias de seguridad, desplegar una aplicación, limpiar archivos temporales, procesar lotes de archivos, generar informes o encadenar varias herramientas. Al convertir un procedimiento en un script, se obtienen tres beneficios importantes: se ahorra tiempo, porque una sola orden hace todo el trabajo; se gana fiabilidad, porque el script ejecuta siempre exactamente los mismos pasos en el mismo orden, sin olvidos ni variaciones; y se documenta el procedimiento, porque el propio script deja constancia de cómo se hace la tarea. Además, un script puede programarse para ejecutarse solo en un momento determinado mediante herramientas de tareas programadas, lo que lleva la automatización un paso más allá al eliminar incluso la necesidad de lanzarlo manualmente.

**¿Qué es el shebang y por qué es importante?**
El shebang es la primera línea de un script y consiste en los caracteres almohadilla y signo de exclamación seguidos de la ruta del intérprete que debe ejecutar el archivo, por ejemplo apuntando a Bash. Su importancia radica en que le indica al sistema operativo con qué programa tiene que interpretar el contenido del script cuando este se ejecuta directamente. Cuando se lanza un archivo ejecutable, el sistema lee esa primera línea para saber si debe pasárselo a Bash, a otro intérprete de shell, a Python o a cualquier otro intérprete, y actúa en consecuencia. Sin un shebang, o con uno incorrecto, el sistema podría intentar ejecutar el script con un intérprete inadecuado o comportarse de forma imprevisible según el contexto. Una forma muy recomendada de escribir el shebang para Bash es usar la ruta del programa env seguida de bash, en lugar de una ruta fija al ejecutable de Bash, porque de esa manera el sistema busca Bash en las ubicaciones estándar y el script funciona correctamente en distintos sistemas donde Bash pueda estar instalado en rutas diferentes, lo que mejora la portabilidad. Conviene tener en cuenta que el shebang solo tiene efecto cuando el script se ejecuta directamente como programa, es decir, tras darle permiso de ejecución y lanzarlo con la notación de directorio actual; si en cambio se ejecuta pasándolo explícitamente a un intérprete, es ese intérprete indicado el que se usa y el shebang se ignora.

**¿Por qué debo poner set -euo pipefail al principio?**
La instrucción set con las opciones e, u y pipefail es una de las prácticas más valiosas para escribir scripts robustos, porque cambia el comportamiento por defecto de Bash, que de otro modo es peligrosamente permisivo. Por defecto, un script de Bash continúa ejecutando las líneas siguientes aunque un comando anterior haya fallado, lo que puede llevar a situaciones desastrosas cuando los pasos posteriores dependían del éxito del anterior. La opción e hace que el script se detenga inmediatamente en cuanto un comando devuelve un error, evitando que siga adelante sobre una base incorrecta. La opción u hace que el script se detenga si se intenta usar una variable que no ha sido definida, lo que atrapa errores muy comunes de tipeo en los nombres de las variables, que de otro modo se tratarían silenciosamente como valores vacíos con consecuencias potencialmente graves. La opción pipefail cambia cómo se evalúa el éxito de una tubería de comandos, de modo que la tubería se considera fallida si falla cualquiera de sus partes, y no solo la última, lo que evita que un error intermedio pase desapercibido. El caso clásico que ilustra la importancia de todo esto es un comando de borrado recursivo que usa una variable de ruta: si esa variable queda vacía por un error, sin estas protecciones el script podría intentar borrar una ubicación completamente equivocada, mientras que con ellas se detendría antes de causar daño. Por eso conviene adoptar estas opciones como hábito al inicio de casi cualquier script serio.

**¿Por qué hay que entrecomillar las variables?**
Entrecomillar las variables, es decir escribir el uso de una variable entre comillas dobles en lugar de dejarla suelta, es una de las prácticas más importantes y a la vez más olvidadas en Bash, y evita una categoría entera de errores sutiles y a veces peligrosos. La razón es cómo Bash trata el contenido de una variable cuando se usa sin comillas: divide ese contenido por los espacios en blanco y, además, interpreta ciertos caracteres especiales como patrones que expande a nombres de archivos. Esto significa que si una variable contiene un valor con espacios, por ejemplo la ruta de una carpeta cuyo nombre tiene un espacio, al usarla sin comillas Bash la partirá en varios argumentos separados, y el comando recibirá algo distinto de lo que se pretendía, lo que puede provocar errores o, peor, que el comando actúe sobre archivos equivocados. Al entrecomillar la variable, en cambio, su contenido se trata como una única unidad literal, respetando los espacios y sin interpretar caracteres especiales, que es casi siempre el comportamiento deseado. El caso más crítico se da en comandos destructivos como los de borrado o movimiento, donde una división inesperada del valor podría afectar a archivos que no se querían tocar. Por todo esto, la recomendación general y prácticamente universal es entrecomillar siempre el uso de las variables, salvo en los pocos casos concretos en que se desee explícitamente la división en palabras o la expansión de patrones.

**¿Cuándo conviene usar Bash y cuándo otro lenguaje?**
Bash es una herramienta excelente para lo que fue diseñado, que es orquestar y encadenar comandos del sistema y automatizar tareas relacionadas con archivos, procesos y herramientas de línea de comandos, pero tiene límites claros más allá de los cuales conviene recurrir a un lenguaje de programación de propósito general como Python. Bash brilla cuando la tarea consiste esencialmente en pegar comandos existentes, moviendo su salida de uno a otro mediante tuberías, comprobando condiciones sencillas y repitiendo acciones sobre listas de archivos; en ese terreno es conciso, directo y está integrado de forma natural con el sistema. Sin embargo, a medida que la lógica se vuelve más compleja, Bash se vuelve difícil de leer y propenso a errores. En particular, cuando hay que manejar datos estructurados como listas o tablas de forma sofisticada, realizar cálculos que no sean triviales, hacer manipulaciones de texto complicadas, gestionar estructuras de datos, o cuando el script crece hasta cientos de líneas con mucha lógica condicional, suele ser preferible pasar a Python u otro lenguaje que ofrezca tipos de datos ricos, mejor manejo de errores, bibliotecas para tareas comunes y una sintaxis más legible y mantenible. Una buena regla práctica es empezar en Bash mientras la tarea sea fundamentalmente encadenar comandos, y considerar el cambio de lenguaje en cuanto aparezca lógica de negocio significativa o la necesidad de estructuras de datos, ya que ese es el punto donde la comodidad inicial de Bash empieza a convertirse en una fuente de fragilidad.

**¿Qué es ShellCheck y por qué usarlo?**
ShellCheck es una herramienta de análisis estático especializada en scripts de shell, es decir, un programa que revisa el código de un script sin ejecutarlo y detecta automáticamente una gran cantidad de errores comunes, malas prácticas y construcciones potencialmente peligrosas. Su valor es enorme para quien escribe scripts, porque muchos de los fallos típicos de Bash son sutiles y no se manifiestan hasta que el script se ejecuta en circunstancias concretas, momento en el que ya pueden haber causado daño. ShellCheck señala precisamente ese tipo de problemas: variables usadas sin entrecomillar que podrían romperse con espacios, referencias a variables no definidas, usos incorrectos de las comparaciones y las condiciones, errores en el manejo de las tuberías, y muchas otras trampas conocidas del lenguaje. Además de detectar los problemas, ofrece explicaciones y sugerencias de corrección, lo que lo convierte también en una excelente herramienta de aprendizaje, ya que enseña las buenas prácticas a medida que las va recomendando. Se puede usar a través de su versión en línea, pegando el script en la web, o integrarlo en el editor de código y en los procesos de integración continua para que revise automáticamente los scripts cada vez que cambian. Incorporar ShellCheck al flujo de trabajo habitual es una de las formas más eficaces y sencillas de elevar la calidad y la seguridad de los scripts, atrapando los errores antes de que lleguen a ejecutarse en un entorno real.

## Fuentes

Documentación oficial y material de la comunidad consultados para esta guía. Fecha de consulta: 28 de julio de 2026.

### Aportes de la comunidad Underc0de

1. **Underc0de, foro.** [Sección GNU/Linux](https://underc0de.org/foro/gnu-linux/). Scripts y automatización en la comunidad.
2. **Underc0de, foro.** [Sección Programación](https://underc0de.org/foro/programacion/). Automatización y scripting.

### Documentación oficial

1. **GNU.** [Bash Reference Manual](https://www.gnu.org/software/bash/manual/bash.html). El manual oficial de Bash.
2. **Google.** [Shell Style Guide](https://google.github.io/styleguide/shellguide.html). Buenas prácticas de estilo.
3. **ShellCheck.** [ShellCheck](https://www.shellcheck.net/). Analizador que detecta errores comunes en scripts.
4. **The Linux Documentation Project.** [Advanced Bash-Scripting Guide](https://tldp.org/LDP/abs/html/). Referencia extensa.

## Guías relacionadas

- [Comandos útiles de Linux](../comandos-utiles-de-linux/index.md)
- [Redirecciones y tuberías](../redirecciones-y-tuberias-en-la-terminal/index.md)
- [Tareas programadas (cron)](../tareas-programadas-en-linux-cron-y-timers/index.md)
- [Permisos en Linux](../permisos-y-propietarios-de-archivos-en-linux/index.md)
- [Índice de Linux y sistemas](../index.md)
