Programación · n.º 5 entre los lenguajes más usados

Aprende Bash y la terminal desde cero

Controla el ordenador con órdenes de texto y automatiza tareas con scripts.

  • 15 lecciones
  • 19 ejercicios interactivos
  • 13 conceptos clave
  • 51,3 % lo usa*

Qué es Bash y la terminal y para qué sirve

Bash es la shell (el intérprete de órdenes) más extendida en Linux y la que encontrarás en servidores, en macOS (que hoy usa zsh, muy parecido) y en Windows a través de WSL. Saber moverte por la terminal y escribir pequeños scripts te ahorra horas de tareas repetitivas.

  • Administrar servidores Linux
  • Automatizar tareas
  • Herramientas de desarrollo y despliegue

Para empezar: En Linux o macOS abre la app Terminal. En Windows instala WSL con Ubuntu y abre su terminal.

Nivel 1 Básico

Lección 1 · Básico

La terminal y tus primeros comandos

La terminal es una ventana donde escribes órdenes y la shell las ejecuta. El texto que aparece antes del cursor es el prompt: suele indicar tu usuario y la carpeta en la que estás.

echo escribe un texto, pwd muestra la carpeta actual y ls lista lo que hay en ella. Muchos comandos aceptan opciones que empiezan por guion, como ls -l para ver detalles.

Ejemplo práctico
echo "Hola desde la terminal"
pwd          # /home/ana
ls           # documentos  fotos  notas.txt
ls -l        # lista con permisos, tamaño y fecha

Ejercicio

¿Qué comando muestra la carpeta en la que estás?

Ver la solución

Respuesta: pwd. pwd (print working directory) muestra la ruta de la carpeta actual.

Lección 2 · Básico

Moverse y manejar archivos

cd cambia de carpeta (cd .. sube una), mkdir crea carpetas, cp copia, mv mueve o renombra y rm borra.

rm no envía nada a la papelera: lo borra directamente. Revisa dos veces antes de usarlo, sobre todo con -r (carpetas enteras).

Ejemplo práctico
mkdir proyecto
cd proyecto
echo "primera nota" > notas.txt
cp notas.txt copia.txt
mv copia.txt antigua.txt
rm antigua.txt
cd ..

Ejercicio

Completa el comando que crea la carpeta «fotos».

 fotos
Ver la solución

Respuesta: mkdir. mkdir (make directory) crea una carpeta nueva.

Lección 3 · Básico

Tu primer script

Un script es un archivo de texto con comandos que se ejecutan en orden. La primera línea, #!/bin/bash (el shebang), indica qué programa debe ejecutarlo.

Para poder lanzarlo con ./script.sh hay que darle permiso de ejecución con chmod +x.

Ejemplo práctico
#!/bin/bash
# saludo.sh
echo "Hoy es $(date +%d/%m/%Y)"
echo "Estás en: $(pwd)"

# En la terminal:
# chmod +x saludo.sh
# ./saludo.sh

Ejercicio

¿Para qué sirve chmod +x saludo.sh?

Ver la solución

Respuesta: Para darle permiso de ejecución. chmod +x añade el permiso de ejecución, necesario para lanzar el archivo como programa.

Lección 4 · Básico

Variables y comillas

Una variable se crea con nombre=valor, sin espacios alrededor del =, y se lee con $nombre. Con $(comando) guardas la salida de un comando.

Entre comillas dobles las variables se sustituyen; entre comillas simples, no. Pon las variables entre comillas dobles para que los espacios no rompan nada.

Ejemplo práctico
nombre="Ana"
archivos=$(ls | wc -l)

echo "Hola, $nombre"     # Hola, Ana
echo 'Hola, $nombre'     # Hola, $nombre (literal)
echo "Hay $archivos elementos aquí"

Ejercicio

¿Por qué falla nombre = "Ana"?

Ver la solución

Respuesta: Porque no puede haber espacios alrededor del =. Con espacios, Bash interpreta nombre como un comando. La asignación se escribe nombre="Ana".

Encuentra los errores

Este script debería mostrar «Hola, Ana». Tiene 2 errores típicos de Bash.

Ver la solución
  • Línea 2: En Bash no puede haber espacios alrededor del =: con espacios, intenta ejecutar una orden llamada nombre. Corrección: nombre="Ana"
  • Línea 3: Entre comillas simples no se sustituyen las variables: se mostraría literalmente $nombre. Hacen falta comillas dobles. Corrección: echo "Hola, $nombre"

Conceptos clave

Nivel 2 Intermedio

Lección 5 · Intermedio

Condiciones

if ejecuta un bloque si un comando termina bien. Lo habitual es usar [[ … ]] para comprobar cosas: -f (existe el archivo), -d (existe la carpeta), -z (texto vacío), y comparar números con -eq, -lt o -gt.

El bloque se cierra con fi (if al revés).

Ejemplo práctico
archivo="notas.txt"

if [[ -f "$archivo" ]]; then
  echo "$archivo existe"
else
  echo "No encuentro $archivo"
fi

edad=20
if [[ $edad -ge 18 ]]; then echo "Mayor de edad"; fi

Ejercicio

Completa la palabra que cierra el bloque.

if [[ -d fotos ]]; then
  echo "Hay carpeta"
Ver la solución

Respuesta: fi. Los bloques if terminan con fi.

Escribe el código

La variable edad ya tiene un número. Escribe un if que muestre «Mayor de edad» si edad es 18 o más y «Menor de edad» en cualquier otro caso.

Tab escribe una sangría; para salir del editor con el teclado, pulsa Esc y luego Tab. Ctrl + Intro corrige.

Ver la solución
edad=20

if [ "$edad" -ge 18 ]; then
  echo "Mayor de edad"
else
  echo "Menor de edad"
fi

[ "$edad" -ge 18 ] compara números (-ge: mayor o igual). También vale la forma aritmética (( edad >= 18 )), donde sí se usan los signos habituales.

Lección 6 · Intermedio

Bucles

for repite órdenes para cada elemento de una lista; con comodines como *.jpg la lista son los archivos que coinciden. while repite mientras se cumpla una condición.

Un uso muy práctico es renombrar o convertir muchos archivos de golpe.

Ejemplo práctico
# Renombra todas las fotos .jpeg a .jpg
for f in *.jpeg; do
  mv -- "$f" "${f%.jpeg}.jpg"
done

# Cuenta atrás
n=3
while [[ $n -gt 0 ]]; do
  echo "$n…"
  n=$((n - 1))
done

Ejercicio

En for f in *.txt, ¿qué contiene f en cada vuelta?

Ver la solución

Respuesta: El nombre de cada archivo .txt. El comodín *.txt se sustituye por los nombres de los archivos que coinciden, y f toma uno en cada vuelta.

Escribe el código

Escribe un bucle for que muestre los números del 1 al 5, cada uno en una línea.

Tab escribe una sangría; para salir del editor con el teclado, pulsa Esc y luego Tab. Ctrl + Intro corrige.

Ver la solución
for i in {1..5}; do
  echo "$i"
done

{1..5} genera la secuencia 1 2 3 4 5 y el bucle ejecuta lo que hay entre do y done una vez por número.

Conceptos clave

Lección 7 · Intermedio

Tuberías y redirecciones

La tubería | pasa la salida de un comando como entrada del siguiente, y así se encadenan herramientas pequeñas: grep filtra líneas, sort ordena, wc -l cuenta.

> guarda la salida en un archivo (sustituyéndolo) y >> la añade al final.

Ejemplo práctico
# ¿Cuántas líneas del registro contienen "error"?
grep -i "error" registro.log | wc -l

# Los 5 archivos más grandes de la carpeta
du -ah . | sort -rh | head -n 5

# Guardar y añadir a un archivo
date > informe.txt
echo "Copia terminada" >> informe.txt

Ejercicio

¿Qué diferencia hay entre > y >>?

Ver la solución

Respuesta: > sustituye el archivo y >> añade al final. > reescribe el archivo desde cero; >> añade el texto al final sin borrar lo anterior.

Nivel 3 Avanzado

Lección 8 · Avanzado

Funciones y argumentos

Un script recibe argumentos: $1 es el primero, $# cuántos hay y "$@" todos ellos. Las funciones funcionan igual, con sus propios $1, $2…

Comprueba siempre que te han pasado lo que necesitas y explica cómo se usa si no.

Ejemplo práctico
#!/bin/bash
# copia.sh: copia un archivo añadiendo la fecha al nombre
copiar_con_fecha() {
  local origen="$1"
  cp -- "$origen" "$origen.$(date +%F)"
}

if [[ $# -lt 1 ]]; then
  echo "Uso: $0 archivo" >&2
  exit 1
fi
copiar_con_fecha "$1"

Ejercicio

Completa la variable que contiene el número de argumentos.

echo "Me has pasado $ argumentos"
Ver la solución

Respuesta: #. $# es el número de argumentos recibidos.

Encuentra los errores

Este script debería mostrar «Hola, Ana». Tiene 2 errores al definir y al usar la función.

Ver la solución
  • Línea 3: $0 es el nombre del script; el primer argumento que recibe la función es $1. Corrección: echo "Hola, $1"
  • Línea 6: En Bash las funciones se llaman como cualquier orden, con los argumentos separados por espacios y sin paréntesis. Corrección: saludar "Ana"

Conceptos clave

Lección 9 · Avanzado

Códigos de salida y errores

Cada comando termina con un código de salida: 0 si fue bien y otro número si falló. $? guarda el del último comando, && ejecuta lo siguiente solo si el anterior fue bien y || solo si falló.

Empezar un script con set -euo pipefail hace que se detenga ante el primer error, una variable sin definir o un fallo dentro de una tubería, en vez de seguir como si nada.

Ejemplo práctico
#!/bin/bash
set -euo pipefail

mkdir -p copias && echo "Carpeta lista"
cp datos.csv copias/ || { echo "No se pudo copiar" >&2; exit 1; }

ls archivo_que_no_existe
echo "Esta línea no se ejecuta: el script ya se ha detenido"

Ejercicio

¿Qué código de salida indica que un comando terminó bien?

Ver la solución

Respuesta: 0. Por convención, 0 significa éxito y cualquier otro valor indica un error.

Lección 10 · Avanzado

Variables de entorno y tareas programadas

Las variables de entorno las heredan los programas que lanzas; export convierte una variable en variable de entorno. PATH es la lista de carpetas donde la shell busca los comandos.

Con cron programas scripts para que se ejecuten solos: crontab -e abre tu lista de tareas, una por línea, con minuto, hora, día, mes, día de la semana y la orden.

Ejemplo práctico
export EDITOR=nano
echo "$PATH"

# Añade tu carpeta de scripts al PATH (en ~/.bashrc)
export PATH="$HOME/bin:$PATH"

# crontab -e → copia de seguridad cada día a las 3:30
30 3 * * * /home/ana/bin/copia.sh /home/ana/documentos

Ejercicio

¿Qué guarda la variable PATH?

Ver la solución

Respuesta: Las carpetas donde se buscan los comandos. Cuando escribes un comando, la shell lo busca en las carpetas de PATH, en orden.

Lección 11 · Avanzado

Buscar texto con grep

grep muestra las líneas de un archivo (o de la salida de otra orden) que contienen un texto. Es la herramienta habitual para revisar registros: encontrar errores, una dirección IP o un usuario entre miles de líneas.

Sus opciones más útiles: -i no distingue mayúsculas, -c cuenta las líneas en vez de mostrarlas, -v muestra las que no coinciden, -r busca en todos los archivos de una carpeta y -E admite expresiones regulares como ERROR|WARN.

Ejemplo práctico
cat > registro.log << 'FIN'
2026-05-01 10:00 INFO  Inicio del servidor
2026-05-01 10:05 ERROR No se encuentra config.yml
2026-05-01 10:07 WARN  Disco al 85 %
2026-05-01 10:09 error Tiempo de espera agotado
FIN

grep "ERROR" registro.log          # solo la línea con ERROR en mayúsculas
grep -i "error" registro.log       # las dos, sin distinguir mayúsculas
grep -c -i "error" registro.log    # 2: cuenta las líneas en vez de mostrarlas
grep -v "INFO" registro.log        # todas menos la que tiene INFO
grep -E "ERROR|WARN" registro.log  # ERROR o WARN

Escribe el código

Escribe una sola orden que cuente cuántas líneas del archivo registro.log contienen la palabra «error», sin distinguir mayúsculas de minúsculas.

Tab escribe una sangría; para salir del editor con el teclado, pulsa Esc y luego Tab. Ctrl + Intro corrige.

Ver la solución
grep -ic "error" registro.log

-i ignora mayúsculas y -c cuenta las coincidencias (se pueden juntar: -ic). grep -i error registro.log | wc -l llega al mismo resultado contando las líneas que muestra.

Lección 12 · Avanzado

Ordenar y contar: sort, uniq y cut

Encadenando órdenes pequeñas con tuberías se responden preguntas sobre un archivo de texto sin abrir una hoja de cálculo. cut se queda con una columna (-d, indica que el separador es la coma y -f2, la segunda columna) y sort ordena las líneas.

uniq -c junta las líneas repetidas y dice cuántas veces aparece cada una, pero solo si están seguidas: por eso siempre va después de sort. Al final, sort -rn ordena de mayor a menor por ese número.

Ejemplo práctico
cat > visitas.csv << 'FIN'
fecha,pagina
2026-05-01,/inicio
2026-05-01,/contacto
2026-05-02,/inicio
2026-05-02,/inicio
2026-05-03,/blog
FIN

# Las páginas más visitadas: sin la cabecera, 2.ª columna, contar y ordenar
tail -n +2 visitas.csv | cut -d, -f2 | sort | uniq -c | sort -rn
#   3 /inicio
#   1 /contacto
#   1 /blog

Ejercicio

¿Por qué hace falta sort antes de uniq -c?

Ver la solución

Respuesta: Porque uniq solo junta las líneas repetidas que están seguidas. Si las líneas iguales están separadas, uniq las cuenta como distintas. Ordenarlas primero las deja juntas.

Lección 13 · Avanzado

Buscar archivos con find

find recorre una carpeta y sus subcarpetas buscando archivos que cumplan condiciones: por nombre (-name, o -iname sin distinguir mayúsculas), tipo (-type f archivos, -type d carpetas), tamaño (-size +10M) o fecha de modificación (-mtime -7: los últimos 7 días).

Con -exec orden {} \; ejecuta una orden por cada archivo encontrado ({} se sustituye por su ruta) y con -delete los borra. Antes de borrar, ejecuta siempre la búsqueda sin -delete para revisar la lista.

Ejemplo práctico
# Archivos .log de más de 10 MB dentro de /var/log
find /var/log -name "*.log" -size +10M

# Fotos .jpg modificadas en los últimos 7 días, en tu carpeta personal
find ~ -type f -iname "*.jpg" -mtime -7

# Archivos .tmp de más de 30 días: primero lístalos y, si son los que esperas, bórralos
find ~/Descargas -name "*.tmp" -mtime +30
find ~/Descargas -name "*.tmp" -mtime +30 -delete

# Dar permiso de ejecución a todos los scripts de la carpeta actual
find . -name "*.sh" -exec chmod +x {} \;

Ejercicio

Completa para buscar todos los PDF de la carpeta actual y sus subcarpetas.

find . -type f - "*.pdf"
Ver la solución

Respuesta: name. -name "*.pdf" busca por nombre con un comodín; -iname haría lo mismo sin distinguir mayúsculas (también encontraría «.PDF»).

Lección 14 · Avanzado

Arrays: listas de valores

Un array guarda varios valores en una sola variable: frutas=("manzana" "pera"). Cada elemento se lee con su posición entre corchetes y llaves (${frutas[0]}, se empieza a contar en 0) y frutas+=("kiwi") añade uno al final.

"${frutas[@]}" son todos los elementos y ${#frutas[@]}, cuántos hay. Las comillas dobles importan: sin ellas, un elemento con espacios como «uva blanca» se partiría en dos.

Ejemplo práctico
frutas=("manzana" "uva blanca" "pera")
frutas+=("kiwi")                  # añadir al final

echo "${frutas[0]}"               # manzana
echo "${#frutas[@]}"              # 4

for fruta in "${frutas[@]}"; do   # con comillas: «uva blanca» es un solo elemento
  echo "- $fruta"
done

Encuentra los errores

Este script debería decir «Hay 3 frutas» y listarlas, con «uva blanca» en una sola línea. Tiene 2 errores.

Ver la solución
  • Línea 3: ${#frutas} es la longitud del primer elemento («manzana», 7 letras). Para contar los elementos se usa ${#frutas[@]}. Corrección: echo "Hay ${#frutas[@]} frutas"
  • Línea 4: Sin comillas, «uva blanca» se separa en dos palabras y el bucle da 4 vueltas. Hay que escribir "${frutas[@]}". Corrección: for f in "${frutas[@]}"; do

Lección 15 · Avanzado

Scripts más seguros: set -euo pipefail

Por defecto, si una orden falla, Bash sigue con la siguiente como si nada. set -e detiene el script en el primer error, set -u lo detiene si usas una variable que no existe (por ejemplo, por una errata en su nombre) y set -o pipefail hace que una tubería falle si falla cualquiera de sus partes.

trap … ERR ejecuta algo justo cuando hay un error, como avisar de la línea, y ${1:?mensaje} detiene el script con ese mensaje si falta el primer argumento. Junto con poner siempre las variables entre comillas, evitan muchos desastres.

Ejemplo práctico
#!/bin/bash
set -euo pipefail
trap 'echo "Error en la línea $LINENO" >&2' ERR

origen="${1:?Indica la carpeta que quieres copiar}"
destino="$HOME/copias/$(date +%F)"

mkdir -p "$destino"
cp -r "$origen" "$destino"
echo "Copia guardada en $destino"

Ejercicio

Con set -u activado, ¿qué pasa si el script usa una variable que no se ha definido?

Ver la solución

Respuesta: El script se detiene con un error. Sin set -u, una variable inexistente vale un texto vacío y, por ejemplo, rm -rf "$carpeta/" podría acabar borrando /.

¿Has terminado? Sigue practicando

Repasa los conceptos en el diccionario, practica con estas herramientas o prueba otro lenguaje: las ideas que has aprendido (variables, condiciones, funciones, objetos…) te servirán en cualquiera.

Proyectos para practicar Bash y la terminal

  • Texto y programación

    Comparar dos textos

    Encuentra las diferencias entre dos versiones de un texto, línea a línea y palabra a palabra.

  • Texto y programación

    Probador de expresiones regulares

    Prueba una expresión regular sobre tu texto, con coincidencias, grupos y explicación en español.

Fuentes consultadas

* Porcentaje de personas que dijeron haber usado Bash en la Stack Overflow Developer Survey 2026: Technology (pregunta sobre lenguajes de programación, de scripts y de marcado; todas las respuestas). El progreso de las lecciones se guarda solo en este navegador.