Publicado el 5 min de lectura

Revisa planes de renombrado de IA sin cambiar archivos

En esta página

Un asistente de IA puede convertir nombres de archivo poco claros en un plan útil. También puede proponer dos destinos idénticos o un nombre que sobrescriba un archivo existente. Pídele una propuesta, no un script con permiso para modificar tu carpeta.

Este tutorial crea un comprobador de Python de solo lectura para pequeños planes de renombrado en JSON. Funciona sin conexión en un sistema de archivos Linux que distingue mayúsculas y minúsculas; no necesitas una cuenta de IA ni paquetes adicionales. Los ejemplos son sintéticos, no resultados medidos de una IA.

Los documentos originales permanecen en una carpeta mientras una lupa revisa etiquetas con nombres propuestos y destaca dos propuestas en conflicto.

1. Separa la propuesta de la ejecución

Proporciona al asistente un inventario de nombres aprobado y estas reglas:

  • Devuelve solo una lista JSON de objetos con source y target.
  • Usa nombres simples, nunca rutas de directorios. Deben empezar por una letra o un dígito ASCII, contener solo letras y dígitos ASCII, puntos, guiones bajos o guiones, y tener como máximo 100 caracteres.
  • Cada origen debe ser un archivo regular existente, no un enlace simbólico. Usa cada origen y destino una sola vez.
  • Nunca elijas un nombre ocupado como destino, aunque otra fila proponga mover ese archivo.

Esto excluye deliberadamente intercambios, cadenas de renombrado, archivos ocultos y nombres con espacios. No envíes nombres privados a servicios no autorizados. Si cambias la regla de nombres, añade primero pruebas de aceptación de regex.

No pruebes un bucle de renombrado escrito por IA con los originales. En Unix, Path.rename() puede sobrescribir un archivo existente si los permisos lo permiten. Python documenta este comportamiento dependiente de la plataforma.

2. Guarda el comprobador de solo lectura

Guarda lo siguiente como audit_renames.py en un directorio de trabajo nuevo. Usa Python 3.10 o posterior. Valida el plan completo antes de mostrar la vista previa y no contiene ninguna operación de renombrado o escritura.

import json
from pathlib import Path
import re
import sys

NAME = re.compile(r"[A-Za-z0-9][A-Za-z0-9._-]{0,99}")


def audit(root, plan_path):
    with open(plan_path, encoding="utf-8") as stream:
        plan = json.load(stream)
    if not isinstance(plan, list) or not plan:
        raise ValueError("plan must be a nonempty list")
    occupied = {entry.name for entry in root.iterdir()}
    sources, targets = set(), set()
    for row in plan:
        if not isinstance(row, dict) or set(row) != {"source", "target"}:
            raise ValueError("each row needs only source and target")
        source, target = row["source"], row["target"]
        if any(not isinstance(n, str) or not NAME.fullmatch(n)
               for n in (source, target)):
            raise ValueError("names must be simple ASCII basenames")
        original = root / source
        if original.is_symlink() or not original.is_file():
            raise ValueError(f"not a regular source file: {source}")
        if source in sources:
            raise ValueError(f"repeated source: {source}")
        if target in occupied:
            raise ValueError(f"target already exists: {target}")
        if target in targets:
            raise ValueError(f"duplicate target: {target}")
        sources.add(source)
        targets.add(target)
    return plan


if __name__ == "__main__":
    if len(sys.argv) != 3:
        raise SystemExit("Usage: python3 audit_renames.py DIRECTORY PLAN.json")
    try:
        plan = audit(Path(sys.argv[1]), sys.argv[2])
    except (OSError, ValueError) as error:
        raise SystemExit(f"FAIL: {error}")
    for row in plan:
        print(f"PREVIEW {row['source']} -> {row['target']}")
    print(f"PASS: {len(plan)} planned renames; no files changed")

El decodificador JSON de la biblioteca estándar lee datos, no código Python ejecutable. Analizar el JSON no impone por sí solo nuestras reglas sobre nombres y colisiones; el bucle añade esas comprobaciones.

3. Crea un conjunto de prueba desechable

Guarda lo siguiente como make_fixture.py, junto al comprobador. Ejecútalo solo en el directorio de trabajo nuevo: crea tres archivos de texto, un enlace simbólico local y siete planes. Los planes comprueban deliberadamente distintos resultados.

import json
from pathlib import Path

root = Path("rename-demo")
root.mkdir()
for name in ("report-01.txt", "report-02.txt", "archive.txt"):
    (root / name).write_text(name + "\n", encoding="utf-8")
(root / "shortcut.txt").symlink_to("report-01.txt")


def row(source, target):
    return {"source": source, "target": target}


plans = {
    "good": [row("report-01.txt", "notes-01.txt"),
             row("report-02.txt", "notes-02.txt")],
    "collision": [row("report-01.txt", "notes.txt"),
                  row("report-02.txt", "notes.txt")],
    "occupied": [row("report-01.txt", "archive.txt")],
    "escape": [row("report-01.txt", "../notes.txt")],
    "missing": [row("report-99.txt", "notes.txt")],
    "repeated": [row("report-01.txt", "notes-01.txt"),
                 row("report-01.txt", "notes-02.txt")],
    "symlink": [row("shortcut.txt", "notes.txt")],
}
for name, plan in plans.items():
    Path(name + ".json").write_text(json.dumps(plan), encoding="utf-8")

El generador de pruebas se niega a reutilizar un directorio rename-demo existente. No necesita tus documentos reales ni una respuesta generada por IA.

4. Ejecuta comprobaciones positivas y negativas

En Bash, ejecuta:

python3 make_fixture.py
for plan in good collision occupied escape missing repeated symlink; do
    python3 audit_renames.py rename-demo "$plan.json"
    echo "exit=$?"
done

No actives set -e en esta demostración: los seis fallos son intencionales. El plan correcto muestra:

PREVIEW report-01.txt -> notes-01.txt
PREVIEW report-02.txt -> notes-02.txt
PASS: 2 planned renames; no files changed

Resultados verificados localmente con Python 3.11.4:

Plan Resultado Código de salida
good Las tres líneas de stdout anteriores; stderr vacío 0
collision FAIL: duplicate target: notes.txt 1
occupied FAIL: target already exists: archive.txt 1
escape FAIL: names must be simple ASCII basenames 1
missing FAIL: not a regular source file: report-99.txt 1
repeated FAIL: repeated source: report-01.txt 1
symlink FAIL: not a regular source file: shortcut.txt 1

Todos los fallos se escriben en stderr y dejan stdout vacío. El bucle de Bash muestra cada código de salida por separado. Los nombres, contenidos y destino del enlace permanecieron intactos tras las siete ejecuciones. Como al probar SQL escrito por IA, los fallos deliberados comprueban que el validador realmente rechaza errores.

5. Resuelve problemas y respeta los límites

  • JSON no válido: elimina los delimitadores Markdown y los comentarios. No ejecutes la respuesta para repararla.
  • Destino ocupado o duplicado: pide otro destino. Nunca evites la comprobación borrando el archivo existente.
  • Origen ausente: actualiza el inventario en lugar de adivinar qué documento se pretendía usar.
  • Se rechazan espacios o letras acentuadas: es una regla limitada del tutorial, no una restricción del sistema de archivos. Amplía explícitamente la política y las pruebas.

Superar las pruebas significa que la propuesta cumple estas comprobaciones, no que los nombres describan correctamente los documentos. Revisa tú el significado y las extensiones. El inventario es una vista momentánea, no un bloqueo del sistema de archivos; los cambios en el directorio pueden invalidarlo. La referencia de iteración de directorios de Python explica que no se especifica la inclusión de archivos añadidos o eliminados durante la iteración.

Esto no es una herramienta de renombrado para producción ni un detector de colisiones portable a Windows y volúmenes que ignoran las mayúsculas. Separa la ejecución, haz copias de seguridad y prueba cualquier ejecutor futuro con copias y sus propios controles para impedir sobrescrituras y recuperar el estado anterior.

Conclusión práctica

Deja que la IA proponga nombres mientras las comprobaciones deterministas rechazan planes defectuosos. Conserva el plan aceptado y su resultado, y añade cada nuevo fallo a tus casos de prueba continua. Una vista previa resulta útil precisamente porque no cambia nada.

Artículos relacionados

Últimos artículos