Subdirectorios
En cuanto un directorio contiene un determinado número de archivos, y éstos se pueden diferenciar por algún criterio, es habitual que el directorio se divida, generándose una estructura de subdirectorios. Un caso concreto de esto son los expedientes SEO. Además de ser una tendencia lógica, que esto se produzca es una medida de la madurez del expediente y de la funcionalidad que éste tiene como recurso de intervención del SEO. Por ello el estudio de la estructura debe ser parte del análisis de los expedientes SEO. Este estudio se puede automatizar mediante script.
Voy a presentar en esta entrada algunos script dirigidos a facilitar la automatización en este nivel, empezando por la identificación del número de subdirectorios que contiene un listado de directorios.
from pathlib import Path
import csv
from collections import Counter
#Función secundaria. Guarda el listado detallado en un archivo CSV.
def crear_csv(datos, ruta_destino):
nombre_archivo = Path(ruta_destino) / "listado_directorios.csv"
try:
with open(nombre_archivo, mode='w', newline='', encoding='utf-8') as f:
escritor = csv.writer(f)
escritor.writerow(["Directorio", "Num_Subcarpetas"])
for fila in datos:
escritor.writerow([fila['nombre'], fila['subs']])
print(f"\n[SISTEMA] Archivo guardado en: {nombre_archivo}")
except Exception as e:
print(f"\n[ERROR] No se pudo crear el CSV: {e}")
# Función secundaria. Calcula y muestra la frecuencia de subdirectorios.
def generar_sintesis(datos):
total_directorios = len(datos)
if total_directorios == 0:
return
frecuencias = Counter(d['subs'] for d in datos)
print("\n--- RESUMEN ESTADÍSTICO DE FRECUENCIAS ---")
for num_subs, cantidad in sorted(frecuencias.items()):
porcentaje = (cantidad / total_directorios) * 100
print(f"CARPETAS con {num_subs} subdirectorios : {cantidad} carpetas -- {porcentaje:.2f}% sobre total")
# Función principal: Coordina el listado, el CSV y la estadística.
def procesar_ruta(ruta_analizar, ruta_guardado):
path_base = Path(ruta_analizar)
if not path_base.exists() or not path_base.is_dir():
print("La ruta proporcionada no es válida.")
return
resultados = []
print(f"\nListado de directorios en: {path_base.resolve()}\n")
for item in path_base.iterdir():
if item.is_dir():
try:
conteo = sum(1 for sub in item.iterdir() if sub.is_dir()) # Contamos subdirectorios inmediatos
resultados.append({'nombre': item.name, 'subs': conteo})
print(f"[DIRECTORIO] {item.name}: {conteo} subcarpetas") # Visualización solicitada
except PermissionError:
continue
crear_csv(resultados, ruta_guardado) # Llamada a funciones secundarias
generar_sintesis(resultados)
# --- LLAMADA A LA FUNCIÓN ---
if __name__ == "__main__":
# Define aquí tus rutas
ruta_objetivo = r"" # Ruta a explorar
ruta_donde_archivar = r"" # Ruta para guardar el CSV
procesar_ruta(ruta_objetivo, ruta_donde_archivar)
Este script lee un conjunto de directorios y genera un listado CSV en el que se recoge el número de subdirectorios que contiene cada uno. Para ello utiliza dos funciones secundarias y una principal. La funcionalidad de cada una de ellas queda explicada en los comentarios del script.
Este otro script añade al anterior el conteo de todos los archivos que contie el directorio.
from pathlib import Path
import csv
from collections import Counter
#Función secundaria. Guarda el listado detallado en un archivo CSV.
def crear_csv(datos, ruta_destino):
nombre_archivo = Path(ruta_destino) / "listado_completo_directorios.csv"
try:
with open(nombre_archivo, mode='w', newline='', encoding='utf-8') as f:
escritor = csv.writer(f)
# Añadimos la nueva columna de archivos totales
escritor.writerow(["Directorio", "Num_Subcarpetas_Directas", "Num_Archivos_Totales"])
for fila in datos:
escritor.writerow([fila['nombre'], fila['subs'], fila['archivos']])
print(f"\n[SISTEMA] Archivo guardado en: {nombre_archivo}")
except Exception as e:
print(f"\n[ERROR] No se pudo crear el CSV: {e}")
#Función secundaria. Calcula y muestra la frecuencia de subdirectorios.
def generar_sintesis(datos):
total_directorios = len(datos)
if total_directorios == 0:
return
frecuencias = Counter(d['subs'] for d in datos)
print("\n" + "="*50)
print("--- RESUMEN ESTADÍSTICO DE FRECUENCIAS ---")
for num_subs, cantidad in sorted(frecuencias.items()):
porcentaje = (cantidad / total_directorios) * 100
print(f"CARPETAS con {num_subs} subdirectorios : {cantidad} carpetas -- {porcentaje:.2f}% sobre total")
print("="*50)
#Función principal. oordina el análisis profundo de la ruta.
def procesar_ruta(ruta_analizar, ruta_guardado):
path_base = Path(ruta_analizar)
if not path_base.exists() or not path_base.is_dir():
print(f"Error: '{ruta_analizar}' no es una ruta válida.")
return
resultados = []
print(f"\nAnalizando contenido en: {path_base.resolve()}\n")
print(f"{'DIRECTORIO':<25} | {'SUBS':<6} | {'ARCHIVOS (TOTAL)'}")
print("-" * 60)
for item in path_base.iterdir():
if item.is_dir():
try:
conteo_subs = sum(1 for sub in item.iterdir() if sub.is_dir()) # 1. Contar subdirectorios directos (primer nivel)
conteo_archivos = sum(1 for f in item.rglob('*') if f.is_file()) # 2. Contar TODOS los archivos rglob('*')
resultados.append({
'nombre': item.name,
'subs': conteo_subs,
'archivos': conteo_archivos
})
print(f"[DIRECTORIO] {item.name:<12}: {conteo_subs:>3} subs | {conteo_archivos:>5} archivos") # Visualización por CMD
except PermissionError:
print(f"[!] Sin permiso para acceder a: {item.name}")
continue
crear_csv(resultados, ruta_guardado) # Ejecución de reportes
generar_sintesis(resultados)
# --- SECCIÓN DE LLAMADA A LA FUNCIÓN ---
if __name__ == "__main__":
# Ajusta estas rutas según tu necesidad
ruta_objetivo = r"" # Ruta a explorar
ruta_donde_archivar = r"" # Ruta para guardar el CSV
procesar_ruta(ruta_objetivo, ruta_donde_archivar)
Finalmente, en este script cambiamos el enfoque y en vez de trabajar con colecciones de directorios lo vamos a hacer con un directorio en concreto, pero incrementando el detalle del estudio de su estructura (subdirectorios) y de su contenido (archivos), generando un informe útil para el estudio estructural del expediente.
from pathlib import Path
import csv
from collections import Counter
#Función secundaria. Guarda el desglose detallado en un archivo CSV.
def crear_csv(datos, ruta_destino):
nombre_archivo = Path(ruta_destino) / "estructura_analizada.csv"
try:
with open(nombre_archivo, mode='w', newline='', encoding='utf-8') as f:
escritor = csv.writer(f)
escritor.writerow([
"Entrada",
"Subcarpetas_Directas",
"Archivos_Raiz",
"Archivos_en_Subdirs",
"Total_Archivos"
])
for fila in datos:
escritor.writerow([
fila['nombre'],
fila['subs'],
fila['archivos_raiz'],
fila['archivos_sub'],
fila['total_archivos']
])
print(f"\n[SISTEMA] Reporte CSV generado en: {nombre_archivo}")
except Exception as e:
print(f"\n[ERROR] No se pudo crear el CSV: {e}")
# Función secundaria. Muestra la estadística de frecuencias por consola.
def generar_sintesis(datos):
total_entradas = len(datos)
if total_entradas == 0:
return
frecuencias = Counter(d['subs'] for d in datos
print("\n" + "="*85)
print("--- RESUMEN ESTADÍSTICO DE FRECUENCIAS (Basado en Subdirectorios Directos) ---")
for num_subs, cantidad in sorted(frecuencias.items()):
porcentaje = (cantidad / total_entradas) * 100
print(f"ENTRADAS con {num_subs} subdirectorios directos: {cantidad} unidades -- {porcentaje:.2f}%")
print("="*85)
# Función principal. Analiza la ruta e incluye el conteo del directorio raíz
def procesar_estructura_principal(ruta_objetivo):
path_base = Path(ruta_objetivo)
if not path_base.exists() or not path_base.is_dir():
print(f"\n[ERROR] La ruta '{ruta_objetivo}' no es válida.")
return
resultados = []
print(f"\nExplorando: {path_base.resolve()}")
header = f"{'ENTRADA/CARPETA':<25} | {'SUBS':<5} | {'RAIZ':<7} | {'EN SUBS':<8} | {'TOTAL'}"
print(header)
print("-" * len(header))
# --- PARTE 1: Analizar la propia carpeta raíz introducida ---
try:
subs_raiz = sum(1 for x in path_base.iterdir() if x.is_dir())
archivos_totales_raiz = sum(1 for x in path_base.rglob('*') if x.is_file())
archivos_directos_raiz = sum(1 for x in path_base.iterdir() if x.is_file())
resultados.append({ # Añadimos la entrada de la carpeta principal
'nombre': f"RAIZ ({path_base.name})",
'subs': subs_raiz,
'archivos_raiz': archivos_directos_raiz,
'archivos_sub': archivos_totales_raiz - archivos_directos_raiz,
'total_archivos': archivos_totales_raiz
})
print(f"{'-- DIRECTORIO RAIZ --':<25} | {subs_raiz:>5} | {archivos_directos_raiz:>7} | {archivos_totales_raiz - archivos_directos_raiz:>8} | {archivos_totales_raiz:>5}")
except PermissionError:
print(f"{'RAIZ':<25} | [!] Acceso denegado")
# --- PARTE 2: Analizar los subdirectorios internos (si los hay) ---
for item in path_base.iterdir():
if item.is_dir():
try:
conteo_subs = sum(1 for x in item.iterdir() if x.is_dir())
total_archivos = sum(1 for x in item.rglob('*') if x.is_file())
if conteo_subs == 0:
archivos_raiz = total_archivos
archivos_en_subdirs = 0
else:
archivos_raiz = sum(1 for x in item.iterdir() if x.is_file())
archivos_en_subdirs = total_archivos - archivos_raiz
resultados.append({
'nombre': item.name,
'subs': conteo_subs,
'archivos_raiz': archivos_raiz,
'archivos_sub': archivos_en_subdirs,
'total_archivos': total_archivos
})
print(f"{item.name[:25]:<25} | {conteo_subs:>5} | {archivos_raiz:>7} | {archivos_en_subdirs:>8} | {total_archivos:>5}")
except PermissionError:
continue
if resultados:
crear_csv(resultados, path_base)
generar_sintesis(resultados)
# --- SEGMENTO DE LLAMADA A LA FUNCIÓN ---
if __name__ == "__main__":
ruta_input = input("Introduce la ruta del directorio a analizar: ").strip().replace('"', '')
procesar_estructura_principal(ruta_input)
No hay comentarios:
Publicar un comentario
Comenta esta entrada