Clase 05 — Funciones
Declarar y llamar funciones
#!/bin/bash
# Forma 1 (recomendada)
saludar() {
echo "¡Hola desde una función!"
}
# Forma 2
function despedir {
echo "¡Adiós desde una función!"
}
# Llamar funciones
saludar
despedir
Funciones con parámetros
#!/bin/bash
# Los parámetros se acceden con $1, $2, etc.
saludar() {
local nombre="$1"
local apellido="$2"
echo "Hola, $nombre $apellido"
}
sumar() {
local a="$1"
local b="$2"
echo "$((a + b))"
}
# Llamar con argumentos
saludar "Roxs" "Ross"
resultado=$(sumar 10 20)
echo "La suma es: $resultado"
Variables locales vs globales
#!/bin/bash
variable_global="Soy global"
mi_funcion() {
local variable_local="Soy local"
variable_global="Modificada desde función"
echo "Dentro de la función:"
echo " Global: $variable_global"
echo " Local: $variable_local"
}
echo "Antes: $variable_global"
mi_funcion
echo "Después: $variable_global"
echo "Local fuera: $variable_local" # Vacía - no existe fuera
Buena práctica
Siempre usá local para variables dentro de funciones para evitar efectos secundarios.
Retornar valores
#!/bin/bash
# Método 1: return (solo para códigos de estado 0-255)
es_par() {
if (( $1 % 2 == 0 )); then
return 0 # true/éxito
else
return 1 # false/fallo
fi
}
if es_par 4; then
echo "4 es par"
fi
if ! es_par 7; then
echo "7 es impar"
fi
# Método 2: echo + sustitución de comando (para valores)
obtener_fecha() {
echo "$(date '+%Y-%m-%d')"
}
fecha=$(obtener_fecha)
echo "Hoy es: $fecha"
# Método 3: Variable global (menos recomendado)
calcular() {
RESULTADO=$(( $1 * $2 ))
}
calcular 5 3
echo "Resultado: $RESULTADO"
Funciones con validación
#!/bin/bash
crear_directorio() {
local dir="$1"
if [[ -z "$dir" ]]; then
echo "ERROR: Se requiere un nombre de directorio" >&2
return 1
fi
if [[ -d "$dir" ]]; then
echo "WARN: El directorio '$dir' ya existe"
return 0
fi
mkdir -p "$dir" && echo "Directorio '$dir' creado" || {
echo "ERROR: No se pudo crear '$dir'" >&2
return 1
}
}
crear_directorio "mi_proyecto"
crear_directorio ""
crear_directorio "mi_proyecto"
Ejemplo: Librería de colores
#!/bin/bash
# colores.sh - Funciones de utilidad para colores en terminal
# Colores
ROJO='\033[0;31m'
VERDE='\033[0;32m'
AMARILLO='\033[0;33m'
AZUL='\033[0;34m'
RESET='\033[0m'
print_info() {
echo -e "${AZUL}[INFO]${RESET} $1"
}
print_ok() {
echo -e "${VERDE}[OK]${RESET} $1"
}
print_warn() {
echo -e "${AMARILLO}[WARN]${RESET} $1"
}
print_error() {
echo -e "${ROJO}[ERROR]${RESET} $1" >&2
}
print_header() {
local texto="$1"
local largo=${#texto}
local linea=$(printf '=%.0s' $(seq 1 $((largo + 4))))
echo ""
echo "$linea"
echo " $texto"
echo "$linea"
echo ""
}
# Uso
print_header "DEPLOY EN PRODUCCIÓN"
print_info "Iniciando deploy..."
print_ok "Imagen Docker construida"
print_warn "La versión anterior será eliminada"
print_error "Falló la conexión a la base de datos"
Ejemplo práctico: Gestor de backups
#!/bin/bash
# backup.sh - Sistema de backup con funciones
BACKUP_DIR="./backups"
LOG_FILE="./backup.log"
log() {
local nivel="$1"
local mensaje="$2"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$nivel] $mensaje" | tee -a "$LOG_FILE"
}
crear_directorio_backup() {
if [[ ! -d "$BACKUP_DIR" ]]; then
mkdir -p "$BACKUP_DIR"
log "INFO" "Directorio de backups creado: $BACKUP_DIR"
fi
}
hacer_backup() {
local origen="$1"
local nombre_backup="$2"
if [[ -z "$origen" ]] || [[ -z "$nombre_backup" ]]; then
log "ERROR" "Uso: hacer_backup <origen> <nombre>"
return 1
fi
if [[ ! -e "$origen" ]]; then
log "ERROR" "El origen '$origen' no existe"
return 1
fi
local fecha=$(date '+%Y%m%d_%H%M%S')
local destino="${BACKUP_DIR}/${nombre_backup}_${fecha}.tar.gz"
tar -czf "$destino" "$origen" 2>/dev/null
if [[ $? -eq 0 ]]; then
local tamano=$(du -h "$destino" | cut -f1)
log "OK" "Backup creado: $destino ($tamano)"
return 0
else
log "ERROR" "Falló el backup de '$origen'"
return 1
fi
}
listar_backups() {
log "INFO" "Listando backups en $BACKUP_DIR"
echo ""
printf "%-40s %-10s %-20s\n" "ARCHIVO" "TAMAÑO" "FECHA"
printf "%-40s %-10s %-20s\n" "--------" "------" "-----"
for f in "$BACKUP_DIR"/*.tar.gz; do
[[ -f "$f" ]] || continue
local nombre=$(basename "$f")
local tamano=$(du -h "$f" | cut -f1)
local fecha=$(stat -f "%Sm" -t "%Y-%m-%d %H:%M" "$f" 2>/dev/null || \
stat --format="%y" "$f" 2>/dev/null | cut -d. -f1)
printf "%-40s %-10s %-20s\n" "$nombre" "$tamano" "$fecha"
done
}
limpiar_backups() {
local dias="${1:-7}"
log "INFO" "Limpiando backups con más de $dias días"
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +"$dias" -delete
log "OK" "Limpieza completada"
}
# --- Ejecución ---
crear_directorio_backup
hacer_backup "/etc/hosts" "hosts"
hacer_backup "$HOME/.bashrc" "bashrc"
listar_backups
Cargar funciones desde otro archivo (source)
#!/bin/bash
# main.sh - Cargar funciones externas
# Cargar librería de funciones
source ./colores.sh
# o también:
# . ./colores.sh
print_header "MI APLICACIÓN"
print_info "Funciones cargadas desde archivo externo"
print_ok "¡Todo listo!"
Funciones recursivas
#!/bin/bash
# Factorial
factorial() {
local n=$1
if (( n <= 1 )); then
echo 1
else
local prev=$(factorial $((n - 1)))
echo $((n * prev))
fi
}
echo "5! = $(factorial 5)"
echo "10! = $(factorial 10)"
# Listar directorio recursivamente (tree casero)
mi_tree() {
local dir="${1:-.}"
local prefix="${2:-}"
for entry in "$dir"/*; do
[[ -e "$entry" ]] || continue
local nombre=$(basename "$entry")
if [[ -d "$entry" ]]; then
echo "${prefix}📁 $nombre/"
mi_tree "$entry" " $prefix"
else
echo "${prefix}📄 $nombre"
fi
done
}
mi_tree "."
Ejercicios
- Creá una función
validar_emailque verifique si un string tiene formato de email - Creá una librería de funciones matemáticas (sumar, restar, multiplicar, dividir) y usala desde otro script con
source - Creá una función que reciba un directorio y devuelva el número total de archivos y su tamaño