Cómo descubrir qué está llenando tu disco en Ubuntu con un Script de Python Personalizado
A todos nos ha pasado: de un momento a otro, Ubuntu nos avisa que nos estamos quedando sin espacio en el disco duro. El problema es que encontrar manualmente cuáles carpetas o archivos residuales están devorando el almacenamiento dentro de nuestra carpeta personal (~) puede ser una tarea titánica y aburrida.
Aunque existen herramientas gráficas como Baobab (Analizador de uso de disco), los entusiastas de la terminal preferimos soluciones rápidas, personalizables y nativas.
En este tutorial te presentaremos un script de Python ultra-elegante que escanea tu directorio Home, calcula dinámicamente el tamaño real de tus archivos y carpetas, y te los presenta en tablas ASCII ordenadas de mayor a menor.
⚠️ Una nota importante sobre Seguridad: 100% Informativo
Antes de empezar, queremos darte total tranquilidad: este script es completamente SEGURO.
Lee también
- Solo lectura: El código no contiene ninguna instrucción de eliminación (os.remove, shutil.rmtree, etc.).
- Propósito exclusivo: Su única función es visualizar y analizar el estado de tu disco.
- Tú tienes el control: Una vez que el script te muestre cuáles son los archivos y carpetas más pesados, serás tú quien decida, de forma manual y consciente, si deseas borrar algo a través del gestor de archivos o de la terminal.
Características principales del Script
- Animación en tiempo real (Spinner): Mientras procesa miles de archivos, verás un indicador visual dinámico en tu terminal para que sepas que sigue trabajando.
- Tablas ASCII elegantes: Los resultados no se muestran como texto plano aburrido; se organizan en tablas ordenadas y estilizadas con colores nativos.
- Filtro inteligente de tamaño (min_mb): Puedes indicarle que ignore archivos o carpetas pequeños (por ejemplo, menores a 100 MB) para enfocarte únicamente en los verdaderos "culpables" del espacio lleno.
- Cálculo preciso: A diferencia de otros scripts básicos, este calcula el peso acumulado de las carpetas de abajo hacia arriba (topdown=False), sumando correctamente el peso de todas las subcarpetas.
El Código Completo
Crea un archivo llamado analizar_espacio.py y pega el siguiente código:Python
import os
import time
import sys
import threading
import itertools
from collections import defaultdict
# --- 1. CLASE PARA COLORES NATIVOS DE TERMINAL ---
class Colores:
MORADO = '\033[95m'
AZUL = '\033[94m'
CYAN = '\033[96m'
VERDE = '\033[92m'
AMARILLO = '\033[93m'
ROJO = '\033[91m'
NEGRO = '\033[90m'
BOLD = '\033[1m'
RESET = '\033[0m'
# --- 2. CLASE PARA LA ANIMACIÓN DE CARGA (SPINNER) ---
class Spinner:
def __init__(self, mensaje="Procesando..."):
self.spinner = itertools.cycle(['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'])
self.detener_evento = threading.Event()
self.mensaje = mensaje
self.hilo = threading.Thread(target=self._girar)
def _girar(self):
while not self.detener_evento.is_set():
sys.stdout.write(f"\r{Colores.CYAN}{Colores.BOLD}{next(self.spinner)} {self.mensaje}{Colores.RESET}")
sys.stdout.flush()
time.sleep(0.1)
sys.stdout.write('\r' + ' ' * (len(self.mensaje) + 5) + '\r')
def iniciar(self):
self.hilo.start()
def detener(self):
self.detener_evento.set()
self.hilo.join()
# --- 3. DIBUJO DE TABLAS ASCII DINÁMICAS ---
def imprimir_tabla(titulo, datos, color_borde):
ancho_tamano = 12
if datos:
ancho_ruta = max(len(ruta) for _, ruta in datos)
else:
print(f"{color_borde}No se encontraron elementos que superen el tamaño mínimo.{Colores.RESET}\n")
return
ancho_total_minimo = len(titulo)
if (ancho_tamano + ancho_ruta) < ancho_total_minimo:
ancho_ruta = ancho_total_minimo - ancho_tamano
print(f"{color_borde}┌{'─' * (ancho_tamano + 2)}┬{'─' * (ancho_ruta + 2)}┐{Colores.RESET}")
print(f"{color_borde}│ {Colores.BOLD}{titulo.center(ancho_tamano + ancho_ruta + 3)}{Colores.RESET}{color_borde} │{Colores.RESET}")
print(f"{color_borde}├{'─' * (ancho_tamano + 2)}┼{'─' * (ancho_ruta + 2)}┤{Colores.RESET}")
print(f"{color_borde}│ {Colores.BOLD}{'Tamaño'.center(ancho_tamano)}{Colores.RESET}{color_borde} │ {Colores.BOLD}{'Ruta'.ljust(ancho_ruta)}{Colores.RESET}{color_borde} │{Colores.RESET}")
print(f"{color_borde}├{'─' * (ancho_tamano + 2)}┼{'─' * (ancho_ruta + 2)}┤{Colores.RESET}")
for tamano, ruta in datos:
ruta_imp = ruta.ljust(ancho_ruta)
print(f"{color_borde}│ {Colores.VERDE}{Colores.BOLD}{tamano:>10}{Colores.RESET}{color_borde} │ {Colores.RESET}{ruta_imp} {color_borde}│{Colores.RESET}")
print(f"{color_borde}└{'─' * (ancho_tamano + 2)}┴{'─' * (ancho_ruta + 2)}┘{Colores.RESET}\n")
def调节_tamano(peso_bytes):
for unidad in ["B", "KB", "MB", "GB", "TB"]:
if peso_bytes < 1024.0:
return f"{peso_bytes:.2f} {unidad}"
peso_bytes /= 1024.0
return f"{peso_bytes:.2f} PB"
def formatear_tamano(peso_bytes):
for unidad in ["B", "KB", "MB", "GB", "TB"]:
if peso_bytes < 1024.0:
return f"{peso_bytes:.2f} {unidad}"
peso_bytes /= 1024.0
return f"{peso_bytes:.2f} PB"
# --- 4. LOGICA DE ANÁLISIS ---
def analizar_carpeta_personal_v2(top_n=15, min_mb=0):
tiempo_inicio = time.time()
home = os.path.expanduser("~")
lista_archivos = []
pesos_carpetas = defaultdict(int)
# Convertimos los Megabytes a Bytes para que Python pueda compararlos
min_bytes = min_mb * 1024 * 1024
print("\n")
spinner = Spinner(f"Escaneando tu carpeta: {home} (Filtro > {min_mb} MB)")
spinner.iniciar()
try:
for raiz, directorios, archivos in os.walk(home, topdown=False):
tamano_archivos_locales = 0
for archivo in archivos:
ruta_completa = os.path.join(raiz, archivo)
if os.path.islink(ruta_completa):
continue
try:
tamano = os.path.getsize(ruta_completa)
tamano_archivos_locales += tamano
# Filtramos los archivos antes de guardarlos en la lista
if tamano >= min_bytes:
lista_archivos.append((ruta_completa, tamano))
except (PermissionError, FileNotFoundError):
continue
tamano_subcarpetas = 0
for d in directorios:
ruta_subcarpeta = os.path.join(raiz, d)
tamano_subcarpetas += pesos_carpetas.get(ruta_subcarpeta, 0)
# Calculamos el peso total de la carpeta
peso_total_carpeta = tamano_archivos_locales + tamano_subcarpetas
# Filtramos las carpetas antes de guardarlas en el diccionario
if peso_total_carpeta >= min_bytes:
pesos_carpetas[raiz] = peso_total_carpeta
finally:
spinner.detener()
archivos_pesados = sorted(lista_archivos, key=lambda x: x[1], reverse=True)[:top_n]
carpetas_pesadas = sorted(pesos_carpetas.items(), key=lambda x: x[1], reverse=True)[:top_n]
datos_archivos = [(formatear_tamano(t), r) for r, t in archivos_pesados]
datos_carpetas = [(formatear_tamano(t), r) for r, t in carpetas_pesadas]
# --- IMPRESIÓN DE RESULTADOS ---
imprimir_tabla(f"📂 TOP {top_n} CARPETAS MÁS PESADAS (> {min_mb} MB)", datos_carpetas, Colores.MORADO)
imprimir_tabla(f"📄 TOP {top_n} ARCHIVOS MÁS PESADOS (> {min_mb} MB)", datos_archivos, Colores.AZUL)
# --- CÁLCULO Y FORMATEO DEL TIEMPO ---
tiempo_fin = time.time()
duracion = tiempo_fin - tiempo_inicio
minutos = int(duracion // 60)
segundos = duracion % 60
if minutos > 0:
texto_tiempo = f" {minutos} min y {segundos:.2f} seg "
else:
texto_tiempo = f" {segundos:.2f} seg "
print(f"{Colores.AMARILLO}╭{'─' * (len(texto_tiempo) + 29)}╮{Colores.RESET}")
print(f"{Colores.AMARILLO}│ {Colores.BOLD}⏱️ Tiempo total de ejecución:{Colores.RESET} {texto_tiempo}{Colores.AMARILLO}│{Colores.RESET}")
print(f"{Colores.AMARILLO}╰{'─' * (len(texto_tiempo) + 29)}╯{Colores.RESET}\n")
if __name__ == "__main__":
# ---> AQUÍ AJUSTAS EL LÍMITE <---
# top_n: cantidad de elementos a mostrar en la tabla.
# min_mb: ignora carpetas/archivos menores a este tamaño en Megabytes.
analizar_carpeta_personal_v2(top_n=50, min_mb=100)
Cómo ejecutar el script en Ubuntu (Paso a Paso)
Dado que Ubuntu trae Python 3 preinstalado de forma nativa, no necesitas configurar entornos virtuales complejos ni instalar librerías externas (pip), ya que todo se ha construido usando módulos estándar de Python.
- Abre la terminal: Puedes usar el atajo de teclado Ctrl + Alt + T.
- Crea el archivo del script: Usa tu editor favorito en la terminal, por ejemplo, nano:
Bash
Lee también
nano analizar_espacio.py
- Pega el código: Copia el script de arriba y pégalo dentro de la terminal (puedes usar Ctrl + Shift + V en Ubuntu).
- Guarda y cierra: En nano, presiona Ctrl + O seguido de Enter para guardar, y luego Ctrl + X para salir.
- Ejecuta el script: Ejecuta el análisis con el siguiente comando:
Bash
python3 analizar_espacio.py
Entendiendo el funcionamiento interno
El núcleo de este script se basa en la función os.walk(home, topdown=False).
- ¿Por qué topdown=False? Esto es fundamental. Significa que Python recorrerá las carpetas desde los niveles más profundos (las subcarpetas más escondidas) hacia arriba. Al hacerlo de esta manera, el script puede sumar el peso de los archivos internos y transferir ese valor exacto a las carpetas contenedoras de forma recursiva.
- El uso de hilos (threading): Escanear un disco entero puede demorar unos segundos o minutos dependiendo de la cantidad de archivos. Para evitar la sensación de que la terminal se ha congelado, la clase Spinner ejecuta la animación de carga en un hilo secundario, manteniendo la interfaz viva mientras el hilo principal hace el trabajo pesado del escaneo.
Cómo personalizar tus búsquedas
Si vas al final del archivo, verás la línea:
Python
analizar_carpeta_personal_v2(top_n=50, min_mb=100)
Puedes editar estos parámetros según lo que necesites:
- Si quieres ver un Top 10 en lugar de 50, cambia top_n=10.
- Si tienes discos muy grandes y solo te importan los archivos gigantescos, puedes subir el filtro cambiando min_mb=500 (para buscar solo cosas mayores a 500 MB) o incluso min_mb=1000 (para mayores a 1 GB).
Conclusión y Limpieza Manual
Una vez que termine el análisis, verás de forma muy visual las rutas exactas de las carpetas de caché, descargas antiguas, entornos virtuales pesados o archivos de video que dabas por olvidados.
Al ser un script completamente pasivo e inofensivo, ahora te toca a ti abrir tu gestor de archivos (Archivos de Ubuntu) o utilizar comandos como rm de manera manual y quirúrgica para eliminar únicamente aquello de lo que estés 100% seguro que puedes prescindir. ¡Feliz limpieza de disco!



