Previsualizar un lote de cambios de nombre antes de aplicarlos
Compara los nombres antiguos y nuevos en una tabla y comprueba conflictos. Solo un --apply explícito crea copias en una carpeta nueva, manteniendo los originales.
Contenido revisado 2026.09.19Incluye archivos de ejemplo
Ver el índice
La traducción se ha realizado con IA. Comprueba el código, las unidades y los valores junto con el original. La revisión por hablantes nativos de cada idioma aún no se ha completado. English
Para quién esPrincipiantes que quieren renombrar varios archivos pero les preocupan las reglas incorrectas o sobrescribir archivos
Preparación
Instala Python 3.12 o posterior y comprueba la versión en una terminal con python --version.
Extrae el ZIP del ejemplo en una carpeta nueva. No ejecutes el ejemplo desde dentro del archivo ZIP.
Abre una terminal en la carpeta que contiene example.py. Si el comando python no está disponible en Windows, utiliza py. En macOS o Linux, utiliza python3 si tu entorno lo requiere.
No se necesitan paquetes externos ni cuentas. Los archivos incluidos son datos sintéticos creados para este tutorial.
01Empieza previsualizando solo tres nombres
En una batch operation, evitar que una rule incorrecta se aplique a todos los files es más importante que detectar un typo en un solo file. Este ejemplo valida toda la name list antes de mostrar el plan. El default command no copia files ni crea folders. Después de comprobar el plan, ejecuta la operación por separado con --apply.
En la carpeta extraída, comprueba mapping.csv y los tres original files dentro de source_files.
Compara old_name y new_name en mapping.csv. La column izquierda es el filename actual; la derecha es el name de la nueva copy.
Ejecuta el default command siguiente y comprueba que los tres pares de names unidos por flechas sean los que querías.
En esta etapa, comprueba que source_files no haya cambiado y que outputs todavía no exista.
bash
python example.py
02Leer el mapping de nombres de archivo
old_name
new_name
메모 초안.txt
note-draft.txt
견적 1.txt
quote-001.txt
사진 설명.txt
photo-notes.txt
Cada mapping row vincula un original con un result. Introduce old_name exactamente como aparece el filename real, incluido el letter case. Toda la operación se detiene si omites un original o añades un name que no existe. Esta rule detecta errores como utilizar un mapping antiguo después de haber añadido un file nuevo a la carpeta.
Los values de new_name se consideran conflictivos incluso si solo difieren en letter case. Esto evita que report.txt y REPORT.txt se conviertan en results separados. También se rechazan leading or trailing spaces, trailing dots, path separators y Windows reserved names. Una persona debe realizar la comprobación final en la preview para confirmar que las naming rules se ajustan a la tarea.
03Código completo utilizado en este ejemplo
make_plan comprueba todos los inputs y conflicts. main imprime el validated plan y después comprueba si se proporcionó --apply. Incluso al aplicar el plan, copia file contents con new names en lugar de utilizar rename sobre los originals, por lo que todavía puedes inspeccionar el starting state.
example.py
"""기본은 미리보기입니다. --apply일 때만 새 이름의 복사본을 만듭니다."""
import argparse
import csv
import re
import shutil
import sys
from pathlib import Path
BASE = Path(__file__).resolve().parent
INPUT = BASE / "source_files"
MAPPING = BASE / "mapping.csv"
OUTPUT = BASE / "outputs"
RESERVED = {"CON", "PRN", "AUX", "NUL"} | {
f"{prefix}{number}" for prefix in ("COM", "LPT") for number in range(1, 10)
}
def validate_name(name):
# 폴더 경로, Windows 예약 이름, 제어 문자 등을 이름으로 받지 않습니다.
if (not name or name in {".", ".."} or name != name.strip()
or name.endswith(".") or re.search(r'[<>:"/\\|?*\x00-\x1f]', name)
or name.split(".")[0].upper() in RESERVED):
raise ValueError(f"사용할 수 없는 파일명: {name!r}")
def make_plan():
if (INPUT.is_symlink() or not INPUT.is_dir()
or getattr(INPUT, "is_junction", lambda: False)()):
raise ValueError("source_files는 실제 폴더여야 합니다.")
if MAPPING.is_symlink():
raise ValueError("mapping.csv 링크는 처리하지 않습니다.")
sources = list(INPUT.iterdir())
if any(path.is_symlink() or not path.is_file() for path in sources):
raise ValueError("source_files에는 일반 파일만 넣으세요.")
if not sources:
raise ValueError("source_files에 파일이 없습니다.")
plan, old_keys, new_keys = [], set(), set()
with MAPPING.open("r", encoding="utf-8-sig", newline="") as stream:
reader = csv.DictReader(stream, strict=True)
if reader.fieldnames != ["old_name", "new_name"]:
raise ValueError("mapping.csv의 열은 old_name,new_name이어야 합니다.")
for row in reader:
if None in row or any(value is None for value in row.values()):
raise ValueError(f"mapping.csv {reader.line_num}행의 열 수를 확인하세요.")
old, new = row["old_name"], row["new_name"]
validate_name(old)
validate_name(new)
if old.casefold() in old_keys:
raise ValueError(f"원본이 중복 지정되었습니다: {old}")
if new.casefold() in new_keys:
raise ValueError(f"새 이름 충돌: {new}")
old_keys.add(old.casefold())
new_keys.add(new.casefold())
plan.append((old, new))
# 한 파일이라도 누락되거나 없는 파일을 지정하면 아무것도 복사하지 않습니다.
if {old for old, _ in plan} != {path.name for path in sources}:
raise ValueError("mapping.csv의 old_name은 원본 파일 전체와 정확히 일치해야 합니다.")
if OUTPUT.exists() or OUTPUT.is_symlink():
raise FileExistsError("outputs가 이미 있습니다. 기존 결과를 옮긴 뒤 실행하세요.")
return plan
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--apply", action="store_true", help="새 이름의 복사본을 outputs/renamed에 만듭니다.")
args = parser.parse_args()
plan = make_plan() # 충돌 검사는 출력 폴더를 만들기 전에 전체에 대해 끝냅니다.
for old, new in plan:
print(f"{old} → {new}")
if not args.apply:
print(f"미리보기: {len(plan)}개. 파일은 변경되지 않았습니다.")
print("이름을 확인한 뒤 python example.py --apply 를 실행하세요.")
return 0
OUTPUT.mkdir()
renamed = OUTPUT / "renamed"
renamed.mkdir()
for old, new in plan:
# 이름 변경 대신 복사합니다. xb는 대상이 생겼으면 덮어쓰지 않고 실패합니다.
with (INPUT / old).open("rb") as source, (renamed / new).open("xb") as target:
shutil.copyfileobj(source, target)
with (OUTPUT / "manifest.csv").open("x", encoding="utf-8-sig", newline="") as stream:
writer = csv.writer(stream)
writer.writerow(["old_name", "new_name"])
writer.writerows(plan)
print(f"완료: {len(plan)}개 복사본 → {renamed}")
return 0
if __name__ == "__main__":
try:
raise SystemExit(main())
except (OSError, ValueError, csv.Error) as error:
print(f"중지: {error}", file=sys.stderr)
raise SystemExit(2)
La opción store_true de argparse hace que preview sea el comportamiento por defecto cuando se omite --apply. Los copy destinations se abren en modo xb para evitar sobrescribir un file que ya existe. El mapping completado también se registra en manifest.csv para poder rastrear un new name hasta su original name.
04Crear copias a partir del plan comprobado
Después de comprobar las tres preview lines, ejecuta el comando siguiente en la misma carpeta. Si editaste mapping.csv después de la preview, vuelve a ejecutar el default command para comprobar el nuevo plan. El apply command no recuerda la preview anterior; vuelve a leer y validar el mapping en el momento de la ejecución.
bash
python example.py --apply
Location
Resultado esperado
source_files/
3 original files conservados con sus nombres actuales
outputs/renamed/
note-draft.txt, quote-001.txt, photo-notes.txt
outputs/manifest.csv
3 rows de mapping original → new name después del header
La terminal muestra “완료: 3개 Copy본” (complete: three copies) y la ruta de la output folder. Abre cada new file para comprobar tanto su content como su name. Por ejemplo, el practice document number de note-draft.txt debería coincidir con el number de 메모 초안.txt.
05Crear un conflicto para comprobar que el script se detiene
Extrae otra copia en una carpeta nueva. No mezcles error tests con una carpeta que ya contenga results.
En mapping.csv, cambia el segundo new_name a note-draft.txt para que coincida con el primero y guarda.
Ejecuta python example.py --apply. Debería aparecer el mensaje “새 이름 충돌” (new-name collision).
Comprueba que no se haya creado ninguna carpeta outputs y que los tres originals permanezcan en source_files.
Restaura los mapping values originales y vuelve a comprobar desde el paso de preview.
Si la validation se hiciera file por file dentro del copy loop, el primer file podría procesarse antes de que el segundo provocara un failure. Este ejemplo comprueba primero todos los names para que estos pre-check errors no causen partial application. También se detiene antes de empezar si outputs ya existe.
06Utilizar tus propias reglas de nombres de documentos
Empieza con una pequeña copy de una sola folder al aplicarlo a tu trabajo. Coloca copies de los originals en source_files y escribe una row por file en mapping.csv. Utiliza el full name, incluida la extension. Una extension no convierte el file format, así que no asignes un text file a un name terminado en .pdf.
Si añades numbers, utiliza una cantidad fija de dígitos como 001 y 002, y un date order coherente para facilitar la búsqueda de results. Acuerda primero qué fields deben formar parte del name y después comprueba su orden y cualquier omission en la preview. Este ejemplo no extrae titles del document content ni infiere tu intent para generar names automáticamente.
07Qué comprobar para cada mensaje de detención
Message
Qué comprobar
Solución
New-name collision (새 이름 충돌)
Values new_name idénticos o que solo difieren en letter case
Elige final names distintos.
Original specified more than once
old_name repetido en dos rows
Mantén una row por original.
Must match the complete set of original files
Un missing file o un typo en old_name
Compara de nuevo el contenido de la folder con el mapping.
Invalid filename
Paths, reserved names, forbidden characters o trailing dots
Introduce solo el filename y elimina restricted characters.
outputs already exists
Results de una copy operation anterior
Renombra la result folder para conservarla y después empieza de nuevo.
Repetir el mismo command después de aplicar un plan no actualiza existing results. Incluso la preview se detiene si encuentra una carpeta outputs existente. Esta rule evita mezclar los results de operaciones separadas. No se proporciona ninguna overwrite option.
08Límites de la copia y comprobaciones que siguen siendo necesarias
Este ejemplo solo lee los original files y da new names a las copies. Mantener tanto los originals como sus copies requiere storage adicional. Conserva el document content, pero no es una herramienta para duplicar creation and modification times, access permissions ni todo el operating-system metadata.
Los errors encontrados antes de copiar, como name conflicts, detienen toda la operación. Una vez que empieza copying, un power failure o insufficient disk space no se revierte como una single transaction. Algunos files pueden permanecer en outputs, así que comprueba el completion message y los tres files. Los concurrent changes en los originals o el mapping por otro programa también requieren un diseño separado.
Registro de ejecución y verificación
2026-09-19 · Windows 11 · CPython 3.12.14 · Sin paquetes adicionales · Ejecutado en una temporary copy de la distribución
La default preview no crea ninguna output folder
Las 3 copies creadas con --apply son byte-for-byte idénticas a los originals
Los conflicts por identical-name y case-only se rechazan antes de crear output
Se rechazan duplicate u omitted originals, nonexistent originals, path traversal y reserved names
Una ejecución repetida se detiene conservando los existing results
Límites de la verificación
Los original files no se renombran.
El partial output no se revierte automáticamente después de un disk error.
El código de ejemplo, los nombres de archivo y las claves de entrada se mantienen como en el original. Consulta también los comandos y los pasos de comprobación del texto traducido.
Material de práctica original · Guarda los archivos originales por separado antes de ejecutarlo.
Fuentes de referencia
Las explicaciones y los ejemplos son de elaboración propia. Puedes consultar los comportamientos y conceptos relacionados en las siguientes fuentes oficiales.
Recorre las subcarpetas y registra en una tabla las rutas, extensiones, tamaños y fechas de modificación de los archivos. Empieza con 4 archivos de ejemplo pequeños, manteniendo intactos los originales y los resultados existentes.
Combina en orden archivos CSV con la misma estructura de columnas y añade una columna source_file. Usa conjuntos de datos pequeños para comprobar nombres de elementos con comas, columnas faltantes y salidas ya existentes.