martes, 31 de marzo de 2026

Datos. Directorios y archivos

Clasificar directorios

Clasificación en función del número de archivos

El objetivo de este script es dividir un conjunto de directorios en dos bloques (directorios principales) en función de un criterio datos. En este caso concreto el criterio tiene que ver con la extensión de los archivos que contienen los directorios.

El contexto concreto en que surge este script es el análisis de los directorios expedientes SEO, en los se ha considerado pertinente diferenciar (en determinados subconjuntos) entre aquellos directorios que cuentan únicamente con determinado tipo de archivos (los llamados archivos-Procesador por derivar del uso de servicios de procesamiento de texto) del resto de los directorios que contienen al menos un archivo que no pertenece a esa categoría.

Para lo que ahora nos insteresa, lo relevante es que el script, además de realizar la identificación en función de ese criterio, debe generar un directorio y trasladar a él un determinado subconjunto de directorios.

Como en otras ocasiones, este script ha sido desarrollado con ayuda de Gemini-IA según procedimiento que se explica aquí (pendiente).

Paso a continuación a desarrollar el análisis del scritp, empezando por la identificación de las bibliotecas necesarias para su ejecución, que son las dos que se indican en el segmento de código que sigue.



#--- Bibliotecas necesarias --------------------------- 

import os
import shutil 


Ambas bibliotecas se usan para el trabajo con directorios y archivos, lo que indica que será ésta la acción que desarrolla la función que sigue y se analiza a continuación.



#--- Función --------------------------------------------------------------------------------

def clasificar_directorios(ruta_base):

# Definición de las extensiones de inclusión y de los identificadores de los grupos
    ext_permitidas = {'.doc', '.docx', '.odt'}
    
    nombre_p = "GRUPO_PROCESADOR"
    nombre_o = "GRUPO_OTROS"

# Planteamiento de la estructura de directorios para contener los directorios categorizados

    ruta_p = os.path.join(ruta_base, nombre_p)
    ruta_o = os.path.join(ruta_base, nombre_o)
    
    for d in [ruta_p, ruta_o]:		# Crear contenedores
        if not os.path.exists(d):
            os.makedirs(d)

# Obtención de los directorios a evaluar según categorias

    elementos = [f for f in os.listdir(ruta_base) 
                 if os.path.isdir(os.path.join(ruta_base, f)) 
                 and f not in [nombre_p, nombre_o]]

    print(f"--- Iniciando análisis en: {ruta_base} ---")
    
    resumen = {nombre_p: 0, nombre_o: 0}

    for carpeta in elementos:
        ruta_carpeta = os.path.join(ruta_base, carpeta)
        es_puro = True
        tiene_contenido = False
        archivo_intruso = None

        for raiz, _, archivos in os.walk(ruta_carpeta): # Búsqueda en profundidad
            for arc in archivos:
                tiene_contenido = True
                ext = os.path.splitext(arc)[1].lower()
                
                if ext not in ext_permitidas:
                    es_puro = False
                    archivo_intruso = arc # Guardamos el nombre para el log
                    break
            if not es_puro:
                break
        
        # Clasificación final. Si está vacío, no es "puro procesador", va a OTROS.
        if es_puro and tiene_contenido:
            destino_final = ruta_p
            grupo_asignado = nombre_p
            print(f"[ACEPTADO] {carpeta}: Todo es procesador.")
        else:
            destino_final = ruta_o
            grupo_asignado = nombre_o
            motivo = f"Intruso hallado: {archivo_intruso}" if tiene_contenido else "Carpeta vacía"
            print(f"[RECHAZADO] {carpeta}: {motivo}. Enviado a OTROS.")

        # Traslado del directorio (expedientes) al directorio de categorización 
        try:
            shutil.move(ruta_carpeta, os.path.join(destino_final, carpeta))
            resumen[grupo_asignado] += 1
        except Exception as e:
            print(f"[ERROR] No se pudo mover {carpeta}: {e}")

# Resumen final por pantalla ----------------------------------------------

    print("\n" + "="*50)
    print("RESUMEN DE DIRECTORIOS CREADOS")
    print("-" * 50)
    print(f"Detección de 'Sólo Procesador': {resumen[nombre_p]} carpetas.")
    print(f"Detección de 'Otros/Mixtos':    {resumen[nombre_o]} carpetas.")
    print("="*50)


En esta función caben diferenciar dos partes muy dispares en extensión y peso en el procedimiento: los procesos que llevan a la identificación, catergorización y manipulación de los directorios y la información sobre los resultados que se muestra por pantalla. Evidentemente lo fundamental de la función pertenece a la primera parte, aunque es la segunda la que permite al usuario acceder a la información que le resulta relevante.

Como ya dije antes, en ese conjunto de procesos se diferencia, a su vez, varias fases, siendo la primera la identificación de los criterios de categorización, la segunda la creación de los directorios de categorización, la tercera la identificación del grupo de pertenencia de cada directorio-expediente (incluye la búsqueda en profundidad de los archivos cada directorio-expediente) y la cuarta el traslado del directorio al directorio de su grupo de pertenencia.

Como corresponde a esta estrucrtura de script, la tercera y última parte es el scritp de ejecución de la función, que contiene la asignación de contenido (identificación de la ruta de trabajo) ruta = r"Mi_Ruta" y la llamada a la función, incorporando el parámetro que requiere clasificar_directorios(ruta).



#--- Ejecución de la función -----------------------------------------

if __name__ == "__main__":
   
    ruta = r"Mi_Ruta"	 			# Sustituir por tu ruta deseada
    clasificar_directorios(ruta)	# Llamada a función


No hay comentarios:

Publicar un comentario

Comenta esta entrada