Curso de programación con Bash
Bash es el shell y lenguaje de scripting para sistemas Unix. Aprende a escribir scripts y automatizar tareas en tu entorno Unix/Linux con Bash.
Bash (Bourne Again SHell) es un intérprete de comandos y lenguaje de scripting que actúa como interfaz entre el usuario y el sistema operativo Unix/Linux. Desarrollada como parte del Proyecto GNU, es una evolución mejorada de la shell Bourne original (sh) que incorpora características de otras shells como Korn shell (ksh) y C shell (csh).
Como shell predeterminada en la mayoría de distribuciones Linux, macOS (hasta Catalina) y disponible en Windows a través de WSL (Windows Subsystem for Linux), Bash se ha convertido en una herramienta esencial para administradores de sistemas, desarrolladores y usuarios avanzados.
Cuando abres una terminal, generalmente interactúas con Bash a través de un prompt que muestra información como tu nombre de usuario, el host y el directorio actual:
usuario@host:~/documentos$
El símbolo $
indica un usuario regular, mientras que #
aparece cuando trabajas como superusuario (root).
Para verificar qué shell estás utilizando:
echo $SHELL
Para conocer la versión de Bash:
bash --version
Sintaxis básica
La estructura general de un comando en Bash es:
comando [opciones] [argumentos]
Por ejemplo:
ls -la /home/usuario
Donde:
ls
es el comando que lista archivos-la
son las opciones (l: formato largo, a: mostrar archivos ocultos)/home/usuario
es el argumento (el directorio a listar)
Puedes ejecutar varios comandos en una misma línea utilizando diferentes separadores:
Punto y coma (;
): Ejecuta los comandos secuencialmente independientemente del resultado.
echo "Primero"; echo "Segundo"
AND lógico (&&
): El segundo comando se ejecuta solo si el primero tiene éxito.
mkdir directorio && cd directorio
OR lógico (||
): El segundo comando se ejecuta solo si el primero falla.
grep "patrón" archivo.txt || echo "Patrón no encontrado"
Los comentarios en Bash comienzan con el símbolo #
:
# Este es un comentario
echo "Hola mundo" # Este es un comentario al final de una línea
Variables
En Bash, las variables se declaran sin especificar tipo:
nombre="Ana"
edad=25
es_estudiante=true
Reglas importantes:
- No debe haber espacios antes ni después del signo igual (
=
) - Los nombres de variables pueden contener letras, números y guiones bajos, pero no pueden comenzar con un número
- Las variables son sensibles a mayúsculas y minúsculas
Para acceder al valor de una variable, se usa el prefijo $
:
echo "Hola, $nombre. Tienes $edad años."
También puedes usar la forma ${variable}
, que es útil para desambiguar:
echo "Hola, ${nombre}s" # Para mostrar "Hola, Anas"
Bash proporciona varias variables especiales:
$0
: Nombre del script$1
,$2
, etc.: Argumentos posicionales$#
: Número de argumentos$@
: Todos los argumentos como palabras separadas$*
: Todos los argumentos como una sola palabra$?
: Código de salida del último comando (0 indica éxito)$$
: PID (Process ID) de la shell actual$!
: PID del último proceso en segundo plano
Las variables de entorno afectan el comportamiento del sistema y los programas:
echo $HOME # Directorio principal del usuario
echo $PATH # Rutas donde se buscan ejecutables
echo $USER # Nombre de usuario actual
Para crear una variable de entorno que esté disponible para los procesos hijo:
export MI_VARIABLE="valor"
Arrays (matrices)
Bash soporta arrays indexados (desde 0) y, en versiones más recientes, arrays asociativos.
Arrays indexados:
# Declaración e inicialización
frutas=("manzana" "naranja" "plátano")
# Acceso a elementos
echo ${frutas[0]} # manzana
# Añadir elemento
frutas+=("uva")
# Mostrar todos los elementos
echo ${frutas[@]}
# Número de elementos
echo ${#frutas[@]}
Arrays asociativos (desde Bash 4.0):
# Declaración (requerida para arrays asociativos)
declare -A colores
# Asignación
colores[rojo]="#FF0000"
colores[verde]="#00FF00"
colores[azul]="#0000FF"
# Acceso
echo ${colores[rojo]}
# Todas las claves
echo ${!colores[@]}
Operadores
Para realizar operaciones aritméticas, Bash ofrece varias sintaxis:
# La forma recomendada
resultado=$((5 + 3))
Operadores disponibles:
+
: Suma-
: Resta*
: Multiplicación/
: División (entera)%
: Módulo (resto)**
: Exponenciación
echo $((10 + 5)) # 15
echo $((10 - 5)) # 5
echo $((10 * 5)) # 50
echo $((10 / 3)) # 3 (división entera)
echo $((10 % 3)) # 1 (resto)
echo $((2 ** 3)) # 8 (potencia)
Para incremento y decremento:
((variable++)) # Incremento después de usar
((++variable)) # Incremento antes de usar
Operadores de comparación numérica (dentro de (( ))
):
if ((a < b)); then
echo "a es menor que b"
fi
==
: Igual!=
: No igual<
: Menor que<=
: Menor o igual>
: Mayor que>=
: Mayor o igual
Operadores de comparación de cadenas (dentro de [[ ]]
):
if [[ "$a" == "$b" ]]; then
echo "Las cadenas son iguales"
fi
==
: Igual!=
: No igual<
: Menor en orden lexicográfico>
: Mayor en orden lexicográfico-z
: Verdadero si la cadena está vacía-n
: Verdadero si la cadena no está vacía
Operadores para comprobación de archivos:
if [[ -f "$archivo" ]]; then
echo "Es un archivo regular"
fi
-f
: Es un archivo regular-d
: Es un directorio-e
: Existe (archivo o directorio)-r
: Tiene permiso de lectura-w
: Tiene permiso de escritura-x
: Tiene permiso de ejecución-s
: Tamaño mayor que cero-L
: Es un enlace simbólico
Estructuras de control
La estructura if
:
if [[ condición ]]; then
# comandos
elif [[ otra_condición ]]; then
# otros comandos
else
# comandos por defecto
fi
Nota: Los espacios dentro de [[ ]]
son importantes.
Estructura case
:
case $variable in
patrón1)
# comandos
;;
patrón2|patrón3)
# comandos para múltiples patrones
;;
*)
# caso por defecto
;;
esac
Bucle for
(varios formatos):
# Iteración sobre lista
for nombre in Juan Ana Pedro; do
echo "Hola, $nombre"
done
# Rango numérico
for i in {1..5}; do
echo "Número: $i"
done
# Sintaxis estilo C
for ((i=0; i<5; i++)); do
echo "Iteración $i"
done
# Iteración sobre archivos
for archivo in *.txt; do
echo "Procesando $archivo"
done
Bucle while
:
contador=0
while [[ $contador -lt 5 ]]; do
echo "Contador: $contador"
((contador++))
done
Bucle until
(continúa hasta que la condición sea verdadera):
contador=0
until [[ $contador -ge 5 ]]; do
echo "Contador: $contador"
((contador++))
done
Control de bucles:
for i in {1..10}; do
if [[ $i -eq 5 ]]; then
continue # Salta a la siguiente iteración
fi
if [[ $i -eq 8 ]]; then
break # Sale del bucle
fi
echo "Número: $i"
done
Funciones
Definición y llamada de funciones:
# Definición con la palabra clave "function"
function saludar {
echo "Hola, $1!"
}
# Forma alternativa
saludar_alternativa() {
echo "Hola, $1!"
}
# Llamada
saludar "Juan"
Las funciones en Bash no devuelven valores como en otros lenguajes, pero existen varias técnicas:
# Usando código de salida
function es_par {
if (( $1 % 2 == 0 )); then
return 0 # verdadero en Bash
else
return 1 # falso en Bash
fi
}
# Verificación
if es_par 4; then
echo "Es par"
fi
# Usando echo y captura
function suma {
echo $(( $1 + $2 ))
}
resultado=$(suma 5 3)
echo "La suma es: $resultado"
Las variables en Bash son globales por defecto, a menos que se declaren como local
:
variable_global="Global"
function prueba_alcance {
local variable_local="Local"
echo "Dentro: global=$variable_global, local=$variable_local"
}
prueba_alcance
echo "Fuera: global=$variable_global"
echo "Intentando acceder a variable local: $variable_local" # Será vacío
Entrada y salida
Para obtener entrada del usuario:
# Lectura básica
echo "Introduce tu nombre:"
read nombre
echo "Hola, $nombre"
# Con prompt incorporado
read -p "Introduce tu edad: " edad
echo "Tienes $edad años"
# Entrada silenciosa (para contraseñas)
read -sp "Contraseña: " password
echo -e "\nContraseña recibida"
Redirección de entrada/salida:
# Redirigir salida estándar a archivo (sobrescribir)
comando > archivo.txt
# Redirigir y anexar salida estándar a archivo
comando >> archivo.txt
# Redirigir error estándar
comando 2> errores.log
# Redirigir ambos (salida y error) a archivos diferentes
comando > salida.txt 2> errores.log
# Redirigir ambos al mismo archivo
comando > archivo.txt 2>&1
# Forma moderna para redirigir ambos
comando &> archivo.txt
# Descartar salida
comando > /dev/null
Las tuberías (pipes) permiten conectar la salida de un comando con la entrada de otro:
# Filtrar resultados
ls -la | grep ".txt"
# Encadenar múltiples comandos
cat archivo.txt | tr '[:lower:]' '[:upper:]' | sort > resultado.txt
# Contar líneas/palabras/caracteres
cat archivo.txt | wc -l
Procesamiento de archivos
Lectura de archivos:
# Línea por línea
while IFS= read -r linea; do
echo "Leído: $linea"
done < archivo.txt
# Todo el archivo de una vez
contenido=$(<archivo.txt)
echo "$contenido"
# Usando IFS para CSV
while IFS=, read -r campo1 campo2 campo3; do
echo "Campo 1: $campo1, Campo 2: $campo2, Campo 3: $campo3"
done < datos.csv
Escritura en archivos:
# Sobrescribir
echo "Nuevo contenido" > archivo.txt
# Añadir
echo "Contenido adicional" >> archivo.txt
# Usando redirección heredoc
cat << EOF > archivo.txt
Línea 1
Línea 2
Línea con variable: $variable
EOF
# Here-doc con variables no expandidas
cat << 'EOF' > archivo.txt
Línea con $variable sin expandir
EOF
Expansiones y sustituciones
Expansión de variables:
nombre="Juan"
echo "${nombre}" # Expansión simple
echo "${nombre}s" # Desambiguación
echo "${nombre:-defecto}" # Valor por defecto si no existe o está vacía
echo "${nombre:=defecto}" # Asignar valor por defecto si no existe o está vacía
echo "${nombre:+alternativo}" # Valor alternativo si existe y no está vacía
echo "${nombre:?mensaje}" # Error con mensaje si no existe o está vacía
Manipulación de cadenas:
cadena="Hola Mundo"
echo "${cadena:5}" # "Mundo" (a partir del índice 5)
echo "${cadena:0:4}" # "Hola" (4 caracteres desde el índice 0)
echo "${#cadena}" # 10 (longitud de la cadena)
# Manipulación de patrones
archivo="imagen.jpg"
echo "${archivo%.jpg}" # "imagen" (elimina .jpg del final)
echo "${archivo#imagen}" # ".jpg" (elimina imagen del principio)
# Sustitución
echo "${cadena/Mundo/Amigo}" # "Hola Amigo" (reemplaza primera coincidencia)
echo "${cadena//o/O}" # "HOla MundO" (reemplaza todas las coincidencias)
# Transformaciones (Bash 4.0+)
echo "${cadena^^}" # "HOLA MUNDO" (todo a mayúsculas)
echo "${cadena,,}" # "hola mundo" (todo a minúsculas)
Expansión de comandos:
# Sintaxis moderna (recomendada)
fecha_actual=$(date)
echo "La fecha actual es: $fecha_actual"
# Anidamiento
echo "Archivos encontrados: $(find . -name "*.txt" | wc -l)"
# Cálculo aritmético
echo "Resultado: $((5 * $(wc -l < archivo.txt)))"
Expansión de llaves:
# Generación de secuencias
echo {1..5} # "1 2 3 4 5"
echo {a..e} # "a b c d e"
echo {1..10..2} # "1 3 5 7 9" (paso de 2)
# Combinaciones
echo file{1,2,3}.txt # "file1.txt file2.txt file3.txt"
echo archivo.{jpg,png,gif} # "archivo.jpg archivo.png archivo.gif"
# Anidamiento
echo {a,b}{1,2} # "a1 a2 b1 b2"
Control de procesos
Ejecución en segundo plano:
# Ejecutar comando en segundo plano
comando &
# Verificar trabajos en ejecución
jobs
# Traer trabajo a primer plano
fg %1
# Enviar trabajo a segundo plano (después de Ctrl+Z)
bg %1
Gestión de procesos:
# Listar procesos
ps aux
ps -ef
# Filtrar procesos
ps aux | grep "firefox"
# Matar proceso por PID
kill 1234
# Forzar terminación
kill -9 1234
# Matar proceso por nombre
pkill firefox
killall firefox
Ejecución condicional y señales:
# Capturar señal Ctrl+C (SIGINT)
trap "echo 'Operación cancelada'; exit" SIGINT
# Limpiar al salir
trap "echo 'Limpiando...'; rm -f /tmp/archivo_temp.$$" EXIT
# Ignorar señal
trap "" SIGTERM
# Restablecer comportamiento predeterminado
trap - SIGINT
Scripting avanzado
Estructura de un script:
#!/bin/bash
# Descripción: Este script hace X
# Autor: Tu nombre
# Fecha: YYYY-MM-DD
# Configuración
set -euo pipefail
# Constantes
readonly CONFIG_FILE="/etc/miapp.conf"
readonly MAX_INTENTOS=3
# Funciones
function log_mensaje() {
local timestamp=$(date "+%Y-%m-%d %H:%M:%S")
echo "[$timestamp] $1"
}
# Código principal
log_mensaje "Iniciando script"
# ... resto del script
log_mensaje "Script completado"
exit 0
Opciones de línea de comandos:
while getopts ":f:v:h" opt; do
case $opt in
f)
archivo="$OPTARG"
;;
v)
nivel_verbosidad="$OPTARG"
;;
h)
echo "Uso: $0 [-f archivo] [-v nivel] [-h]"
exit 0
;;
\?)
echo "Opción inválida: -$OPTARG" >&2
exit 1
;;
:)
echo "La opción -$OPTARG requiere un argumento." >&2
exit 1
;;
esac
done
Manejo de errores:
# Salir al primer error
set -e
# Detectar uso de variables no definidas
set -u
# Propagar errores en tuberías
set -o pipefail
# Todo junto (recomendado para scripts robustos)
set -euo pipefail
# Función de error
function error_salida() {
local linea=$1
local mensaje=$2
echo "Error en línea $linea: $mensaje" >&2
exit 1
}
# Usar trap para capturar errores con información de línea
trap 'error_salida ${LINENO} "$BASH_COMMAND"' ERR
Inclusión de archivos:
# Cargar funciones o variables de otro archivo
source funciones.sh
# o
. funciones.sh
# Verificar si el archivo existe antes de incluirlo
if [[ -f config.sh ]]; then
source config.sh
else
echo "Archivo de configuración no encontrado" >&2
exit 1
fi
Buenas prácticas
Seguridad:
# Comillas en variables para evitar problemas con espacios
echo "Procesando archivo: \"$archivo\""
# Validar entrada antes de usar
if [[ ! $numero =~ ^[0-9]+$ ]]; then
echo "Error: '$numero' no es un número válido" >&2
exit 1
fi
# Evitar inyección de comandos
archivo_seguro=$(printf '%q' "$nombre_archivo")
eval "cp $archivo_seguro /destino/"
Portabilidad:
# Usar shebang con env para mayor portabilidad
#!/usr/bin/env bash
# Comprobar disponibilidad de comandos
if ! command -v jq &> /dev/null; then
echo "Error: jq no está instalado" >&2
exit 1
fi
# Establecer ruta predeterminada para comandos
PATH="/usr/local/bin:/usr/bin:/bin"
Eficiencia:
# Evitar llamadas externas innecesarias
if [[ "$cadena" == *"subcadena"* ]]; then # Expansión de patrón nativa
echo "Contiene subcadena"
fi
# Uso de parámetros nativos
echo "${#cadena}" # en lugar de echo "$cadena" | wc -c
# Usar mapeos internos para transformaciones simples
echo "${cadena^^}" # en lugar de echo "$cadena" | tr '[:lower:]' '[:upper:]'
Depuración:
# Mostrar comandos al ejecutarse
set -x
comando1
comando2
set +x
# Solo activar depuración si se establece una variable
if [[ "${DEBUG:-}" == "true" ]]; then
set -x
fi
# Ejecutar script con depuración
bash -x script.sh
Tutoriales de Bash
Aprende Bash con tutoriales de programación en Bash.
Principales Distribuciones De Linux
Introducción Y Entorno
Instalar Ubuntu En Windows Con Wsl
Introducción Y Entorno
Introducción A Shell Y Bash
Introducción Y Entorno
Comandos De Navegación Pwd, Cd Y Ls
Navegación
Manipulación De Archivos Y Directorios
Navegación
Comprimir Y Descomprimir Archivos En Bash
Navegación
Manipulación De Permisos De Archivos Y Directorios
Navegación
Redirección Y Tuberías
Navegación
Enlaces Simbólicos Y Duros
Navegación
Gestión De Procesos Con Ps, Htop Y Pgrep
Procesos Y Servicios
Gestión De Servicios Con Systemd
Procesos Y Servicios
Configuración De Bash
Interacción Con El Sistema
Redes Y Comunicación
Interacción Con El Sistema
Transferencia De Archivos Y Comunicación Remota Con Ssh
Interacción Con El Sistema
Gestión De Paquetes Y Actualización Del Sistema
Interacción Con El Sistema
Variables Y Tipos De Datos
Sintaxis Scripting
Operadores
Sintaxis Scripting
Sintaxis De Control De Flujo
Sintaxis Scripting
Expresiones Regulares Y Manipulación De Texto
Sintaxis Scripting
Definición Y Uso De Funciones
Sintaxis Scripting
Evaluación Bash
Evaluación
Ejercicios de programación de Bash
Evalúa tus conocimientos en Bash con ejercicios de programación Bash de tipo Test, Puzzle, Código y Proyecto con VSCode.
Transferencia de archivos y comunicación remota con SSH
Tareas de automatización de PostgreSQL
Redes y comunicación con ifconfig, ip y netstat
Comandos de navegación
Principales distribuciones de Linux
Evaluación Conocimiento general de Bash
Gestión de paquetes y actualización del sistema
Sintaxis de control de flujo
Operadores
Redirección y tuberías
Introducción a Shell y Bash
Manipulación de permisos de archivos y directorios
Gestión de procesos con ps, htop y pgrep
Configuración de Bash
Expresiones regulares y manipulación de texto
Instalar Ubuntu en Windows con WSL
Gestión de servicios con systemd
Variables y tipos de datos
Manipulación de archivos y directorios
Definición y uso de funciones
Comprimir y descomprimir archivos
Tipo de tecnología
Lenguaje
Categoría laboral
Administración de sistemas
Año de lanzamiento
1989
Developers
Chet Ramey
Todos los módulos del curso de Bash
Bash
Introducción y entorno
Bash
Navegación
Bash
Procesos y servicios
Bash
Interacción con el sistema
Bash
Sintaxis scripting
Bash
Evaluación
Otras tecnologías
Rust
Rust
Backend
Lenguaje de programación de sistemas enfocado en seguridad, concurrencia y rendimiento.
C
C
Backend
Lenguaje de propósito general, eficiente y de bajo nivel.
R
R
Ciencia de Datos e IA
Lenguaje para análisis estadístico, manipulación de datos y visualización gráfica.
TypeScript
TypeScript
Full Stack
Superconjunto de JavaScript con tipado estático.
PySpark
PySpark
Big Data
Motor unificado de análisis de datos distribuido para grandes volúmenes.
Go
Go
Backend
Lenguaje de programación eficiente y concurrente creado por Google.
Django
Django
Backend
Framework web Python para desarrollo rápido y seguro.
SpringBoot
SpringBoot
Backend
Framework para desarrollo rápido de aplicaciones Java.
Laravel
Laravel
Backend
Framework de PHP para desarrollo web backend.
Node
Node
Backend
Node.js es un entorno de ejecución de JavaScript basado en el motor V8 de Google.
Java
Java
Backend
Lenguaje de programación versátil y multiplataforma.
OpenCV
OpenCV
Ciencia de Datos e IA
Biblioteca de Python para Computer Vision en imágenes y vídeos.
Flask
Flask
Backend
Microframework web para Python, simple y flexible.
Nest
Nest
Backend
Framework Node.js para crear aplicaciones escalables y eficientes.
Selenium
Selenium
Testing / QA
Suite de herramientas open-source para automatizar navegadores web y pruebas de software de interfaz de usuario.
React
React
Frontend
Librería framework para frontend interfaces de usuario.
Vuejs
Vuejs
Frontend
Framework de JS progresivo para construir interfaces de usuario reactivas y modulares.
Docker
Docker
DevOps
Plataforma de contenedores para aplicaciones portátiles.
PHP
PHP
Backend
Lenguaje de programación para desarrollo web del lado del servidor, el motor del ecosistema Wordpress.
CSharp
CSharp
Backend
Lenguaje C# de Microsoft para desarrollo en el ecosistema .NET para todo tipo de aplicaciones.
Streamlit
Streamlit
Ciencia de Datos e IA
Biblioteca Python para prototipado web UI rápido en ciencia de datos.
Seaborn
Seaborn
Ciencia de Datos e IA
Biblioteca de visualización de datos para Python.
SQL
SQL
Bases de datos
Lenguaje para gestionar bases de datos relacionales.
FastAPI
FastAPI
Backend
Framework web moderno y rápido para Python.
Fundamentos
Fundamentos
Full Stack
Fundamentos y bases de la programación de software moderna.
TensorFlow
TensorFlow
Ciencia de Datos e IA
Biblioteca Python para redes neuronales en Deep Learning
TailwindCSS
TailwindCSS
Frontend
Framework de utilidades CSS para diseños rápidos y personalizables.
Git
Git
DevOps
Sistema de control de versiones distribuido.
ScikitLearn
ScikitLearn
Ciencia de Datos e IA
Biblioteca de aprendizaje automático en Python.
Kotlin
Kotlin
Backend
Lenguaje de programación moderno y seguro para aplicaciones Android.
Numpy
Numpy
Ciencia de Datos e IA
Biblioteca Python para computación científica y matrices.
HTML
HTML
Frontend
Lenguaje de marcado para estructurar contenido web.
Bootstrap
Bootstrap
Frontend
Framework CSS para diseños web responsive y modernos.
Matplotlib
Matplotlib
Ciencia de Datos e IA
Biblioteca Python para crear gráficos y visualizaciones.
Hibernate
Hibernate
Backend
ORM para Java, simplifica el acceso a bases de datos.
Pandas
Pandas
Ciencia de Datos e IA
Herramienta Python para análisis y manipulación de datos.
JavaScript
JavaScript
Full Stack
Lenguaje de scripting para desarrollo web interactivo.
Angular
Angular
Frontend
Framework web de Google para aplicaciones dinámicas.
CSS
CSS
Frontend
Lenguaje de estilo para diseñar páginas web atractivas.
Python
Python
Backend
Lenguaje de programación fácil de aprender y versátil.