Глава 23 · Часть IV · Реализуем SafeSort
Что делать, если имя уже занято
Ни на диске, ни внутри одного плана два файла никогда не получат одинаковое имя назначения.
SafeSort · Часть 4 из 6Реализация
Handle destination name collisions
Area: SafetyPriority: Medium
git switch -c feat/plan-and-collisions
Два файла с одинаковым именем могут попасть в одну и ту же категорию — например, два
разных notes.txt из разных подкаталогов исходного каталога.
Если бы SafeSort просто перемещал файл поверх существующего, второй файл исчез бы молча —
в каталоге назначения осталось бы одно и то же имя notes.txt,
но с содержимым только одного из двух файлов, без единого предупреждения об этом.
Sorted/documents/
notes.txt
notes (1).txtНОВОЕ
SafeSort никогда не решает конфликт имён перезаписью: вместо этого он находит свободное имя по понятной схеме.
src/safesort/planner.py
def _resolve_collision(candidate: Path, reserved: set[Path]) -> Path:
if candidate not in reserved and not candidate.exists():
return candidate
stem, suffix, parent = candidate.stem, candidate.suffix, candidate.parent
counter = 1
while True:
alternative = parent / f"{stem} ({counter}){suffix}"
if alternative not in reserved and not alternative.exists():
return alternative
counter += 1
Пример
otchet.pdf уже существует в Sorted/documents/
→ следующий otchet.pdf получит имя otchet (1).pdf
→ если и оно занято — otchet (2).pdf, и так далее
reserved — конфликты внутри одного плана, не только на диске
Проверки
not candidate.exists() достаточно для конфликта с уже существующим файлом на диске — но не для случая, когда два файла из одного и того же плана претендуют на одинаковое имя одновременно, пока ни один из них ещё не перемещён. Множество reserved запоминает уже занятые в этом плане имена, поэтому второй файл получит otchet (1).pdf, даже если на диске пока нет ни одного otchet.pdf.Практика: безопасное имя при конфликте
Интерактивный ноутбук прямо в браузере — Python 3.14 через Pyodide, без установки
Чекпойнт · Issue #6
git commit -m "feat: add safe organization plan with collision handling"
Та же ветка и тот же Pull Request #17, который закрыл Issue #3 на странице 23-11. план и обработка конфликта имён были одной, тесно связанной задачей в терминах кода, но остаются двумя разными Issues и двумя разными уроками.
Статус в реальном Project: Done