Proyecto 2: Organizador de Archivos por Tipo
🧭 Navegación:
- Anterior: Copias de Seguridad Automáticas
- Siguiente: Web Scraping Básico
📁 El problema: El caos digital
¿Te resulta familiar tener una carpeta de descargas llena de archivos de todo tipo? ¿O un escritorio tan abarrotado de documentos que es imposible encontrar lo que buscas? El desorden digital es un problema común que afecta nuestra productividad y eficiencia.
Mantener los archivos organizados manualmente es:
- Tedioso y repetitivo
- Propenso a errores
- Consumidor de tiempo
- Fácil de postergar
La solución es crear un sistema automatizado que organice los archivos según su tipo, moviendo cada uno a la carpeta correspondiente.
🎯 Objetivo del proyecto
Desarrollaremos un script de Python que:
- Analice una carpeta desordenada (como Descargas o Escritorio)
- Identifique el tipo de cada archivo según su extensión
- Cree carpetas organizadas por categorías (Documentos, Imágenes, Videos, etc.)
- Mueva cada archivo a la carpeta correspondiente
- Genere un informe de la organización realizada
- Pueda ejecutarse manualmente o programarse para correr periódicamente
📋 Planificación del sistema
Componentes principales:
- Análisis: Escanear la carpeta y clasificar los archivos
- Categorización: Definir categorías y asignar extensiones a cada una
- Organización: Crear carpetas y mover archivos
- Informes: Generar resumen de las acciones realizadas
- Configuración: Permitir personalizar el comportamiento
Bibliotecas que utilizaremos:
import os # Para operaciones con el sistema de archivos
import shutil # Para mover archivos
import datetime # Para registrar fechas en informes
import logging # Para registrar eventos
import json # Para manejar configuraciones
import argparse # Para procesar argumentos de línea de comandos
💻 Implementación paso a paso
Paso 1: Definir categorías y extensiones
Primero, crearemos un mapeo entre extensiones de archivo y categorías:
# file_categories.py
# Mapeo de extensiones a categorías
FILE_CATEGORIES = {
# Documentos
"Documentos": [
# Documentos de texto
"pdf", "doc", "docx", "txt", "rtf", "odt",
# Hojas de cálculo
"xls", "xlsx", "csv", "ods",
# Presentaciones
"ppt", "pptx", "odp",
# Otros documentos
"md", "epub", "mobi"
],
# Imágenes
"Imagenes": [
"jpg", "jpeg", "png", "gif", "bmp", "svg",
"tiff", "webp", "ico", "raw", "psd", "ai"
],
# Audio
"Audio": [
"mp3", "wav", "ogg", "flac", "aac", "wma",
"m4a", "mid", "midi"
],
# Video
"Videos": [
"mp4", "avi", "mkv", "mov", "wmv", "flv",
"webm", "m4v", "mpg", "mpeg", "3gp"
],
# Archivos comprimidos
"Comprimidos": [
"zip", "rar", "7z", "tar", "gz", "bz2",
"xz", "iso"
],
# Código y programación
"Codigo": [
"py", "js", "html", "css", "java", "c", "cpp",
"h", "cs", "php", "rb", "go", "rs", "swift",
"json", "xml", "yaml", "yml", "sql", "sh", "bat"
],
# Ejecutables e instaladores
"Ejecutables": [
"exe", "msi", "apk", "dmg", "deb", "rpm"
]
}
# Función para obtener la categoría de un archivo según su extensión
def get_file_category(filename):
"""
Determina la categoría de un archivo basado en su extensión.
Args:
filename: Nombre del archivo a categorizar
Returns:
str: Nombre de la categoría o 'Otros' si no coincide con ninguna
"""
# Obtener la extensión (sin el punto)
extension = filename.split('.')[-1].lower() if '.' in filename else ""
# Buscar la categoría correspondiente
for category, extensions in FILE_CATEGORIES.items():
if extension in extensions:
return category
# Si no coincide con ninguna categoría conocida
return "Otros"
Paso 2: Crear la clase principal del organizador
# file_organizer.py
import os
import shutil
import logging
import datetime
from file_categories import get_file_category
class FileOrganizer:
"""Clase para organizar archivos por tipo."""
def __init__(self, source_dir, organize_directories=False):
"""
Inicializa el organizador de archivos.
Args:
source_dir: Directorio a organizar
organize_directories: Si True, también organiza subdirectorios
"""
self.source_dir = os.path.abspath(source_dir)
self.organize_directories = organize_directories
self.stats = {
"total_files": 0,
"organized_files": 0,
"skipped_files": 0,
"categories": {}
}
# Configurar logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler(os.path.join(self.source_dir, "organizer_log.txt")),
logging.StreamHandler()
]
)
self.logger = logging.getLogger()
def organize(self):
"""Organiza los archivos en el directorio fuente."""
self.logger.info(f"Iniciando organización de archivos en: {self.source_dir}")
# Verificar que el directorio existe
if not os.path.exists(self.source_dir):
self.logger.error(f"El directorio {self.source_dir} no existe.")
return False
# Obtener lista de archivos (no directorios)
items = os.listdir(self.source_dir)
self.stats["total_files"] = len(items)
# Procesar cada elemento
for item_name in items:
item_path = os.path.join(self.source_dir, item_name)
# Saltar el archivo de log
if item_name == "organizer_log.txt":
continue
# Verificar si es un directorio
if os.path.isdir(item_path):
if self.organize_directories:
# Si queremos organizar directorios, tratarlos como archivos
self._process_item(item_path)
else:
self.logger.info(f"Saltando directorio: {item_name}")
self.stats["skipped_files"] += 1
else:
# Procesar archivo
self._process_item(item_path)
# Generar informe
self._generate_report()
return True
def _process_item(self, item_path):
"""
Procesa un archivo o directorio y lo mueve a la categoría correspondiente.
Args:
item_path: Ruta completa al elemento a procesar
"""
item_name = os.path.basename(item_path)
# Determinar categoría
category = get_file_category(item_name)
# Crear directorio de destino si no existe
dest_dir = os.path.join(self.source_dir, category)
if not os.path.exists(dest_dir):
os.makedirs(dest_dir)
self.logger.info(f"Creado directorio: {category}")
# Ruta de destino
dest_path = os.path.join(dest_dir, item_name)
# Verificar si ya existe un archivo con el mismo nombre
if os.path.exists(dest_path):
# Añadir timestamp al nombre para evitar sobreescritura
name, ext = os.path.splitext(item_name)
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
new_name = f"{name}_{timestamp}{ext}"
dest_path = os.path.join(dest_dir, new_name)
self.logger.warning(f"Archivo ya existe, renombrando a: {new_name}")
try:
# Mover el archivo
shutil.move(item_path, dest_path)
self.logger.info(f"Movido: {item_name} -> {category}/{os.path.basename(dest_path)}")
# Actualizar estadísticas
self.stats["organized_files"] += 1
if category not in self.stats["categories"]:
self.stats["categories"][category] = 0
self.stats["categories"][category] += 1
except Exception as e:
self.logger.error(f"Error al mover {item_name}: {str(e)}")
self.stats["skipped_files"] += 1
def _generate_report(self):
"""Genera un informe de la organización realizada."""
report = [
"=" * 50,
"INFORME DE ORGANIZACIÓN DE ARCHIVOS",
"=" * 50,
f"Fecha: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
f"Directorio: {self.source_dir}",
"-" * 50,
f"Total de elementos: {self.stats['total_files']}",
f"Archivos organizados: {self.stats['organized_files']}",
f"Elementos omitidos: {self.stats['skipped_files']}",
"-" * 50,
"Distribución por categorías:"
]
# Añadir estadísticas por categoría
for category, count in self.stats["categories"].items():
report.append(f"- {category}: {count} archivos")
report.extend([
"=" * 50,
"Organización completada con éxito.",
"=" * 50
])
# Guardar informe en archivo
report_path = os.path.join(self.source_dir, "organizacion_informe.txt")
with open(report_path, "w", encoding="utf-8") as f:
f.write("\n".join(report))
self.logger.info(f"Informe generado: {report_path}")
# También mostrar en consola
print("\n".join(report))
Paso 3: Script principal con interfaz de línea de comandos
# organize_files.py
import argparse
import os
from file_organizer import FileOrganizer
def main():
"""Función principal del programa."""
# Configurar el parser de argumentos
parser = argparse.ArgumentParser(
description="Organizador automático de archivos por tipo"
)
parser.add_argument(
"directory",
nargs="?",
default=os.getcwd(),
help="Directorio a organizar (por defecto: directorio actual)"
)
parser.add_argument(
"-d", "--dirs",
action="store_true",
help="Organizar también subdirectorios"
)
# Parsear argumentos
args = parser.parse_args()
# Verificar que el directorio existe
if not os.path.exists(args.directory):
print(f"Error: El directorio '{args.directory}' no existe.")
return 1
# Crear y ejecutar el organizador
organizer = FileOrganizer(args.directory, args.dirs)
success = organizer.organize()
return 0 if success else 1
if __name__ == "__main__":
exit(main())
🚀 Uso del sistema
Uso básico
Para organizar el directorio actual:
python organize_files.py
Para organizar un directorio específico:
python organize_files.py /ruta/a/mi/carpeta/desordenada
Para incluir subdirectorios en la organización:
python organize_files.py -d /ruta/a/mi/carpeta
Automatización periódica
En Windows:
Puedes crear una tarea programada para ejecutar el script periódicamente:
- Abre el Programador de tareas
- Crea una nueva tarea básica
- Configúrala para que se ejecute diariamente o semanalmente
- Apunta al script con los parámetros deseados
En Linux:
Puedes usar cron para programar la ejecución:
# Editar crontab
crontab -e
# Añadir una línea para ejecutar el script todos los viernes a las 8 PM
0 20 * * 5 python /ruta/a/organize_files.py /ruta/a/descargas
🔍 Comprueba tu comprensión
- ¿Qué sucedería si dos archivos con el mismo nombre pertenecen a la misma categoría?
- ¿Cómo modificarías el código para manejar archivos sin extensión?
- ¿Qué estrategia usarías para organizar archivos basándote en su contenido en lugar de su extensión?
- ¿Cómo adaptarías el sistema para permitir configuraciones personalizadas de categorías?
🛠️ Ideas para mejoras
- Configuración personalizada: Permitir al usuario definir sus propias categorías y extensiones
- Modo simulación: Mostrar qué cambios se harían sin realizar movimientos reales
- Organización por fecha: Agrupar archivos por fecha de creación o modificación
- Detección inteligente: Usar el contenido del archivo para determinar su tipo, no solo la extensión
- Interfaz gráfica: Crear una GUI para facilitar el uso
- Integración con el sistema: Añadir opciones al menú contextual del explorador de archivos
- Filtros avanzados: Permitir incluir o excluir archivos según patrones
📝 Resumen
En este proyecto, has creado un sistema de organización de archivos que:
- Clasifica automáticamente archivos según su tipo
- Crea una estructura de carpetas ordenada
- Maneja conflictos de nombres de archivo
- Genera informes detallados de las acciones realizadas
- Puede ejecutarse desde la línea de comandos con opciones configurables
Este organizador no solo te ayudará a mantener tu espacio digital ordenado, sino que también te ha permitido aplicar conceptos importantes de Python como el manejo de archivos y directorios, la creación de clases, el procesamiento de argumentos de línea de comandos y la generación de informes.
En el próximo proyecto, aprenderemos a extraer información de sitios web con web scraping.