Descripción del curso 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)
Guarda tu progreso
Inicia sesión para no perder tu progreso y accede a miles de tutoriales, ejercicios prácticos y nuestro asistente de IA.
Más de 25.000 desarrolladores ya confían en CertiDevs
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
Completa este curso de Bash y certifícate
Únete a nuestra plataforma de cursos de programación y accede a miles de tutoriales, ejercicios prácticos, proyectos reales y nuestro asistente de IA personalizado para acelerar tu aprendizaje.
Asistente IA
Resuelve dudas al instante
Ejercicios
Practica con proyectos reales
Certificados
Valida tus conocimientos
Más de 25.000 desarrolladores ya se han certificado con CertiDevs