Aprende a comprimir, archivar y gestionar backups
La compresión reduce el tamaño de archivos y directorios para ahorrar espacio en disco y acelerar transferencias. En Linux tenemos varias herramientas:
#!/bin/bash
# Crear archivo tar
tar -cf archivo.tar directorio/
# Crear tar con compresión gzip
tar -czf archivo.tar.gz directorio/
# Crear tar con compresión bzip2
tar -cjf archivo.tar.bz2 directorio/
# Crear tar con compresión xz
tar -cJf archivo.tar.xz directorio/
# Listar contenido sin extraer
tar -tf archivo.tar.gz
# Extraer archivo tar
tar -xf archivo.tar
# Extraer tar comprimido
tar -xzf archivo.tar.gz
# Extraer a directorio específico
tar -xzf archivo.tar.gz -C /ruta/destino/
# Extraer archivos específicos
tar -xzf archivo.tar.gz archivo1.txt directorio/archivo2.txt
#!/bin/bash
# advanced_tar.sh - Script avanzado de archivado
create_archive() {
local source="$1"
local destination="$2"
local compression="$3"
local exclude_pattern="$4"
local verbose="$5"
if [[ ! -e "$source" ]]; then
echo "Error: Fuente no existe - $source"
return 1
fi
# Configurar opciones de tar
local tar_opts="-c"
local extension=""
case "$compression" in
"gzip"|"gz")
tar_opts="${tar_opts}z"
extension=".tar.gz"
;;
"bzip2"|"bz2")
tar_opts="${tar_opts}j"
extension=".tar.bz2"
;;
"xz")
tar_opts="${tar_opts}J"
extension=".tar.xz"
;;
"none"|"")
extension=".tar"
;;
*)
echo "Compresión no soportada: $compression"
return 1
;;
esac
# Agregar verbosity si se solicita
if [[ "$verbose" == "true" ]]; then
tar_opts="${tar_opts}v"
fi
# Agregar opción de archivo
tar_opts="${tar_opts}f"
# Construir nombre de archivo de destino
if [[ -z "$destination" ]]; then
destination="$(basename "$source")_$(date +%Y%m%d_%H%M%S)${extension}"
elif [[ ! "$destination" =~ \.(tar|tar\.gz|tar\.bz2|tar\.xz)$ ]]; then
destination="${destination}${extension}"
fi
echo "Creando archivo: $destination"
echo "Fuente: $source"
echo "Compresión: ${compression:-none}"
# Ejecutar tar con exclusiones si se especifican
if [[ -n "$exclude_pattern" ]]; then
tar $tar_opts "$destination" --exclude="$exclude_pattern" "$source"
else
tar $tar_opts "$destination" "$source"
fi
if [[ $? -eq 0 ]]; then
echo "Archivo creado exitosamente: $destination"
echo "Tamaño: $(du -h "$destination" | cut -f1)"
# Calcular ratio de compresión si hay compresión
if [[ "$compression" != "none" && -n "$compression" ]]; then
local original_size=$(du -sb "$source" | cut -f1)
local compressed_size=$(stat -f%z "$destination" 2>/dev/null || stat -c%s "$destination" 2>/dev/null)
local ratio=$((100 - (compressed_size * 100 / original_size)))
echo "Ratio de compresión: ${ratio}%"
fi
else
echo "Error al crear archivo"
return 1
fi
}
extract_archive() {
local archive="$1"
local destination="$2"
local verbose="$3"
if [[ ! -f "$archive" ]]; then
echo "Error: Archivo no existe - $archive"
return 1
fi
# Crear directorio de destino si no existe
if [[ -n "$destination" ]]; then
mkdir -p "$destination"
fi
local tar_opts="-x"
# Detectar tipo de compresión automáticamente
case "$archive" in
*.tar.gz|*.tgz)
tar_opts="${tar_opts}z"
;;
*.tar.bz2|*.tbz2)
tar_opts="${tar_opts}j"
;;
*.tar.xz|*.txz)
tar_opts="${tar_opts}J"
;;
*.tar)
# Sin compresión
;;
*)
echo "Tipo de archivo no reconocido: $archive"
return 1
;;
esac
if [[ "$verbose" == "true" ]]; then
tar_opts="${tar_opts}v"
fi
tar_opts="${tar_opts}f"
echo "Extrayendo: $archive"
if [[ -n "$destination" ]]; then
echo "Destino: $destination"
tar $tar_opts "$archive" -C "$destination"
else
tar $tar_opts "$archive"
fi
if [[ $? -eq 0 ]]; then
echo "Extracción completada exitosamente"
else
echo "Error durante la extracción"
return 1
fi
}
show_archive_info() {
local archive="$1"
if [[ ! -f "$archive" ]]; then
echo "Error: Archivo no existe - $archive"
return 1
fi
echo "=== Información del Archivo ==="
echo "Archivo: $archive"
echo "Tamaño: $(du -h "$archive" | cut -f1)"
echo "Fecha de modificación: $(stat -f%Sm "$archive" 2>/dev/null || stat -c%y "$archive" 2>/dev/null)"
echo ""
echo "=== Contenido del Archivo ==="
tar -tvf "$archive" | head -20
local total_files=$(tar -tf "$archive" | wc -l)
echo ""
echo "Total de archivos: $total_files"
if [[ $total_files -gt 20 ]]; then
echo "(Mostrando solo los primeros 20 archivos)"
fi
}
# Función principal con menú interactivo
main() {
if [[ $# -eq 0 ]]; then
echo "=== Herramienta de Archivado TAR ==="
echo "1. Crear archivo"
echo "2. Extraer archivo"
echo "3. Ver información de archivo"
echo "4. Ayuda"
read -p "Seleccione opción [1-4]: " option
case "$option" in
1)
read -p "Ruta a archivar: " source
read -p "Archivo de destino (opcional): " dest
read -p "Compresión (gzip/bzip2/xz/none) [gzip]: " comp
read -p "Patrón de exclusión (opcional): " exclude
read -p "Modo verboso (y/N): " verbose
comp=${comp:-gzip}
[[ "$verbose" =~ ^[Yy]$ ]] && verbose="true" || verbose="false"
create_archive "$source" "$dest" "$comp" "$exclude" "$verbose"
;;
2)
read -p "Archivo a extraer: " archive
read -p "Directorio de destino (opcional): " dest
read -p "Modo verboso (y/N): " verbose
[[ "$verbose" =~ ^[Yy]$ ]] && verbose="true" || verbose="false"
extract_archive "$archive" "$dest" "$verbose"
;;
3)
read -p "Archivo a inspeccionar: " archive
show_archive_info "$archive"
;;
4)
echo "Uso directo:"
echo "$0 create [destino] [compresión] [exclusión] [verbose]"
echo "$0 extract [destino] [verbose]"
echo "$0 info "
;;
esac
else
case "$1" in
"create")
create_archive "$2" "$3" "$4" "$5" "$6"
;;
"extract")
extract_archive "$2" "$3" "$4"
;;
"info")
show_archive_info "$2"
;;
*)
echo "Comando no reconocido: $1"
echo "Comandos disponibles: create, extract, info"
;;
esac
fi
}
# Ejecutar función principal
main "$@"
#!/bin/bash
# Comprimir archivo
gzip archivo.txt # Crea archivo.txt.gz y elimina original
# Comprimir manteniendo original
gzip -c archivo.txt > archivo.txt.gz
# Descomprimir
gunzip archivo.txt.gz # Restaura archivo.txt
# Ver contenido sin descomprimir
zcat archivo.txt.gz
# Comprimir con máxima compresión
gzip -9 archivo.txt
# Comprimir múltiples archivos
gzip archivo1.txt archivo2.txt archivo3.txt
#!/bin/bash
# Crear archivo ZIP
zip archivo.zip archivo1.txt archivo2.txt
# Crear ZIP de directorio recursivamente
zip -r directorio.zip directorio/
# Crear ZIP con contraseña
zip -P contraseña archivo.zip archivo.txt
# Agregar archivos a ZIP existente
zip archivo.zip archivo3.txt
# Extraer ZIP
unzip archivo.zip
# Extraer a directorio específico
unzip archivo.zip -d /ruta/destino/
# Listar contenido sin extraer
unzip -l archivo.zip
# Testear integridad
unzip -t archivo.zip
#!/bin/bash
# smart_compress.sh - Compresión inteligente según tipo de archivo
compress_smart() {
local source="$1"
local format="$2"
local level="$3"
if [[ ! -e "$source" ]]; then
echo "Error: Fuente no existe - $source"
return 1
fi
# Detectar mejor formato si no se especifica
if [[ -z "$format" ]]; then
if file "$source" | grep -q "text"; then
format="gzip" # Mejor para texto
elif [[ -d "$source" ]]; then
format="tar.xz" # Mejor para directorios
else
format="gzip" # Por defecto
fi
echo "Formato detectado automáticamente: $format"
fi
level=${level:-6} # Nivel de compresión por defecto
case "$format" in
"gzip"|"gz")
if [[ -f "$source" ]]; then
gzip -c -$level "$source" > "${source}.gz"
else
tar -czf "${source}.tar.gz" "$source"
fi
;;
"bzip2"|"bz2")
if [[ -f "$source" ]]; then
bzip2 -c -$level "$source" > "${source}.bz2"
else
tar -cjf "${source}.tar.bz2" "$source"
fi
;;
"xz")
if [[ -f "$source" ]]; then
xz -c -$level "$source" > "${source}.xz"
else
tar -cJf "${source}.tar.xz" "$source"
fi
;;
"zip")
if [[ -f "$source" ]]; then
zip -$level "${source}.zip" "$source"
else
zip -r -$level "${source}.zip" "$source"
fi
;;
"7z")
if command -v 7z >/dev/null 2>&1; then
7z a -mx=$level "${source}.7z" "$source"
else
echo "7z no está instalado"
return 1
fi
;;
"tar.gz"|"tgz")
tar -czf "${source}.tar.gz" "$source"
;;
"tar.bz2"|"tbz2")
tar -cjf "${source}.tar.bz2" "$source"
;;
"tar.xz"|"txz")
tar -cJf "${source}.tar.xz" "$source"
;;
*)
echo "Formato no soportado: $format"
return 1
;;
esac
# Mostrar estadísticas
local original_size=$(du -sb "$source" | cut -f1)
local compressed_file=""
case "$format" in
"gzip"|"gz") compressed_file="${source}.gz" ;;
"bzip2"|"bz2") compressed_file="${source}.bz2" ;;
"xz") compressed_file="${source}.xz" ;;
"zip") compressed_file="${source}.zip" ;;
"7z") compressed_file="${source}.7z" ;;
"tar.gz"|"tgz") compressed_file="${source}.tar.gz" ;;
"tar.bz2"|"tbz2") compressed_file="${source}.tar.bz2" ;;
"tar.xz"|"txz") compressed_file="${source}.tar.xz" ;;
esac
if [[ -f "$compressed_file" ]]; then
local compressed_size=$(stat -f%z "$compressed_file" 2>/dev/null || stat -c%s "$compressed_file" 2>/dev/null)
local ratio=$((100 - (compressed_size * 100 / original_size)))
echo "=== Estadísticas de Compresión ==="
echo "Archivo original: $(numfmt --to=iec $original_size)"
echo "Archivo comprimido: $(numfmt --to=iec $compressed_size)"
echo "Ratio de compresión: ${ratio}%"
echo "Archivo creado: $compressed_file"
fi
}
benchmark_compression() {
local source="$1"
if [[ ! -e "$source" ]]; then
echo "Error: Fuente no existe - $source"
return 1
fi
echo "=== Benchmark de Compresión para: $source ==="
local formats=("gzip" "bzip2" "xz" "zip")
for format in "${formats[@]}"; do
echo "Probando $format..."
local start_time=$(date +%s.%N)
compress_smart "$source" "$format" 6
local end_time=$(date +%s.%N)
local duration=$(echo "$end_time - $start_time" | bc)
echo "Tiempo: ${duration}s"
echo ""
done
}
# Función principal
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
case "$1" in
"compress")
compress_smart "$2" "$3" "$4"
;;
"benchmark")
benchmark_compression "$2"
;;
*)
echo "Uso: $0 [compress|benchmark] [formato] [nivel]"
echo ""
echo "Formatos soportados: gzip, bzip2, xz, zip, 7z, tar.gz, tar.bz2, tar.xz"
echo "Niveles de compresión: 1 (rápido) a 9 (máximo)"
;;
esac
fi
#!/bin/bash
# backup_system.sh - Sistema completo de backups automáticos
BACKUP_BASE_DIR="/backups"
CONFIG_FILE="$HOME/.backup_config"
LOG_FILE="/var/log/backup.log"
RETENTION_DAYS=30
# Configuración por defecto
DEFAULT_CONFIG="# Configuración de Backups
BACKUP_SOURCES=('/home/user/Documents' '/etc' '/var/log')
BACKUP_EXCLUDE_PATTERNS=('*.tmp' '*.cache' '.git' 'node_modules')
COMPRESSION='xz'
ENCRYPTION=false
ENCRYPTION_KEY=''
REMOTE_BACKUP=false
REMOTE_HOST=''
REMOTE_PATH=''
EMAIL_NOTIFICATIONS=false
EMAIL_ADDRESS=''
RETENTION_DAYS=30"
# Crear configuración si no existe
if [[ ! -f "$CONFIG_FILE" ]]; then
echo "$DEFAULT_CONFIG" > "$CONFIG_FILE"
echo "Archivo de configuración creado en: $CONFIG_FILE"
fi
# Cargar configuración
source "$CONFIG_FILE"
log_message() {
local level="$1"
local message="$2"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$level] $message" | tee -a "$LOG_FILE"
}
send_notification() {
local subject="$1"
local message="$2"
if [[ "$EMAIL_NOTIFICATIONS" == "true" && -n "$EMAIL_ADDRESS" ]]; then
echo "$message" | mail -s "$subject" "$EMAIL_ADDRESS"
fi
}
create_backup() {
local source="$1"
local backup_name="$(basename "$source")_$(date +%Y%m%d_%H%M%S)"
local backup_dir="$BACKUP_BASE_DIR/$(date +%Y/%m)"
# Crear directorio de backup
mkdir -p "$backup_dir"
log_message "INFO" "Iniciando backup de: $source"
# Preparar opciones de exclusión
local exclude_opts=""
for pattern in "${BACKUP_EXCLUDE_PATTERNS[@]}"; do
exclude_opts="$exclude_opts --exclude=$pattern"
done
# Crear backup según compresión configurada
local backup_file=""
case "$COMPRESSION" in
"gzip"|"gz")
backup_file="$backup_dir/${backup_name}.tar.gz"
tar $exclude_opts -czf "$backup_file" "$source"
;;
"bzip2"|"bz2")
backup_file="$backup_dir/${backup_name}.tar.bz2"
tar $exclude_opts -cjf "$backup_file" "$source"
;;
"xz")
backup_file="$backup_dir/${backup_name}.tar.xz"
tar $exclude_opts -cJf "$backup_file" "$source"
;;
*)
backup_file="$backup_dir/${backup_name}.tar"
tar $exclude_opts -cf "$backup_file" "$source"
;;
esac
if [[ $? -eq 0 ]]; then
log_message "INFO" "Backup creado: $backup_file"
# Encriptar si está habilitado
if [[ "$ENCRYPTION" == "true" && -n "$ENCRYPTION_KEY" ]]; then
encrypt_backup "$backup_file"
fi
# Verificar integridad
verify_backup "$backup_file"
# Backup remoto si está configurado
if [[ "$REMOTE_BACKUP" == "true" ]]; then
sync_to_remote "$backup_file"
fi
return 0
else
log_message "ERROR" "Fallo al crear backup de: $source"
return 1
fi
}
encrypt_backup() {
local backup_file="$1"
if command -v gpg >/dev/null 2>&1; then
log_message "INFO" "Encriptando backup: $backup_file"
gpg --batch --yes --passphrase "$ENCRYPTION_KEY" \
--symmetric --cipher-algo AES256 "$backup_file"
if [[ $? -eq 0 ]]; then
rm "$backup_file" # Eliminar versión no encriptada
log_message "INFO" "Backup encriptado: ${backup_file}.gpg"
else
log_message "ERROR" "Fallo al encriptar backup"
fi
else
log_message "WARNING" "GPG no disponible - backup no encriptado"
fi
}
verify_backup() {
local backup_file="$1"
log_message "INFO" "Verificando integridad de: $backup_file"
case "$backup_file" in
*.tar.gz)
if gzip -t "$backup_file" >/dev/null 2>&1; then
log_message "INFO" "Verificación exitosa"
else
log_message "ERROR" "Backup corrupto: $backup_file"
return 1
fi
;;
*.tar.bz2)
if bzip2 -t "$backup_file" >/dev/null 2>&1; then
log_message "INFO" "Verificación exitosa"
else
log_message "ERROR" "Backup corrupto: $backup_file"
return 1
fi
;;
*.tar.xz)
if xz -t "$backup_file" >/dev/null 2>&1; then
log_message "INFO" "Verificación exitosa"
else
log_message "ERROR" "Backup corrupto: $backup_file"
return 1
fi
;;
*.tar)
if tar -tf "$backup_file" >/dev/null 2>&1; then
log_message "INFO" "Verificación exitosa"
else
log_message "ERROR" "Backup corrupto: $backup_file"
return 1
fi
;;
esac
}
sync_to_remote() {
local backup_file="$1"
if [[ -n "$REMOTE_HOST" && -n "$REMOTE_PATH" ]]; then
log_message "INFO" "Sincronizando a servidor remoto: $backup_file"
rsync -avz "$backup_file" "${REMOTE_HOST}:${REMOTE_PATH}/"
if [[ $? -eq 0 ]]; then
log_message "INFO" "Sincronización remota exitosa"
else
log_message "ERROR" "Fallo en sincronización remota"
fi
fi
}
cleanup_old_backups() {
log_message "INFO" "Limpiando backups antiguos (>${RETENTION_DAYS} días)"
find "$BACKUP_BASE_DIR" -type f -name "*.tar*" -mtime +$RETENTION_DAYS -delete
find "$BACKUP_BASE_DIR" -type f -name "*.gpg" -mtime +$RETENTION_DAYS -delete
# Eliminar directorios vacíos
find "$BACKUP_BASE_DIR" -type d -empty -delete
log_message "INFO" "Limpieza completada"
}
run_backup() {
log_message "INFO" "=== Iniciando proceso de backup ==="
local failed_backups=0
local total_backups=0
for source in "${BACKUP_SOURCES[@]}"; do
if [[ -e "$source" ]]; then
((total_backups++))
if ! create_backup "$source"; then
((failed_backups++))
fi
else
log_message "WARNING" "Fuente no existe: $source"
fi
done
# Limpiar backups antiguos
cleanup_old_backups
# Reporte final
local successful_backups=$((total_backups - failed_backups))
log_message "INFO" "=== Proceso completado ==="
log_message "INFO" "Exitosos: $successful_backups, Fallidos: $failed_backups"
# Notificación
if [[ $failed_backups -eq 0 ]]; then
send_notification "Backup Exitoso" "Todos los backups ($total_backups) se completaron exitosamente."
else
send_notification "Backup con Errores" "$failed_backups de $total_backups backups fallaron. Revisar logs."
fi
return $failed_backups
}
# Función principal
case "$1" in
"run")
run_backup
;;
"test")
log_message "INFO" "Modo de prueba - configuración actual:"
echo "Fuentes: ${BACKUP_SOURCES[*]}"
echo "Compresión: $COMPRESSION"
echo "Encriptación: $ENCRYPTION"
echo "Backup remoto: $REMOTE_BACKUP"
;;
"config")
echo "Editando configuración..."
${EDITOR:-nano} "$CONFIG_FILE"
;;
*)
echo "Sistema de Backup Automático"
echo "Uso: $0 [run|test|config]"
echo ""
echo " run - Ejecutar backup completo"
echo " test - Mostrar configuración actual"
echo " config - Editar configuración"
;;
esac
Crea un script que:
Desarrolla un sistema que:
Implementa un backup que: