Кейс — скрипт на один вечер
самый опасный жанр
Что это
Последний кейс — самый маленький и самый опасный. Задача на двадцать строк: разложить папку с фотографиями, переименовав файлы по дате съёмки.
Опасность у таких скриптов не в сложности, а в том, что к ним не относятся серьёзно. Мини-ТЗ не пишут, тесты не пишут, ревью не делают — «это же просто переименование». И запускают сразу на настоящей папке.
Шаг 1. Что пришло
Напиши скрипт на питоне, который переименует все файлы
в папке photos по дате изменения, формат ГГГГ-ММ-ДД.import os
from datetime import datetime
from pathlib import Path
folder = Path("photos")
for f in folder.iterdir():
date = datetime.fromtimestamp(f.stat().st_mtime)
new_name = date.strftime("%Y-%m-%d") + f.suffix
f.rename(folder / new_name)Девять строк, читаются целиком, делают ровно то, что просили. Трудно представить, что здесь можно сломать.
Шаг 2. Что он сделал
В папке было четыре файла:
IMG_1001.jpg "first photo" снято 14 марта
IMG_1002.jpg "second photo" снято 14 марта
IMG_1003.jpg "third photo" снято 15 марта
notes.txt "not a photo"После запуска:
2026-03-14.jpg "second photo"
2026-03-15.jpg "third photo"
2026-03-15.txt "not a photo"Файлов стало три. first photo больше нет нигде.
Две фотографии одного дня получили одно и то же имя, и вторая молча записалась
поверх первой: rename в Python не спрашивает разрешения и не предупреждает.
Заодно переименовался notes.txt, который никто не просил трогать.
Ни ошибки, ни предупреждения, ни кода возврата. Скрипт отработал успешно.
Шаг 3. Как надо было просить
Скрипт на Python 3.12: переименовать фотографии в папке
по дате изменения файла в формат ГГГГ-ММ-ДД.
Обязательно:
- по умолчанию НИЧЕГО не менять, только показать план
«старое имя -> новое»; выполнять по флагу --apply
- если на одну дату несколько файлов: -2, -3 и так далее
- если целевое имя уже занято файлом не из этого списка —
остановиться и ничего не делать
- трогать только .jpg/.jpeg/.png/.heic, остальное
пропустить и перечислить
- папку принимать аргументом, не вшиватьШесть строк требований на девять строк кода. Выглядит избыточно ровно до первой потерянной фотографии.
Главная из них — первая. Режим показа по умолчанию превращает опасный скрипт в безопасный: сначала смотришь, что произойдёт, потом разрешаешь.
Шаг 4. Что получилось
$ python3 rename.py photos
IMG_1001.jpg -> 2026-03-14.jpg
IMG_1002.jpg -> 2026-03-14-2.jpg
IMG_1003.jpg -> 2026-03-15.jpg
пропущено (не фото): notes.txt
ничего не изменено. файлов к переименованию: 3
повторите с --apply, чтобы выполнитьПлан видно целиком, и видно главное: два файла от 14 марта получат разные имена. Теперь можно разрешать:
$ python3 rename.py photos --apply
...
переименовано: 3Итог:
2026-03-14.jpg "first photo"
2026-03-14-2.jpg "second photo"
2026-03-15.jpg "third photo"
notes.txt "not a photo"Четыре файла вошли, четыре вышли. Ничего не потеряно, notes.txt не тронут.
Шаг 5. Правило для всего жанра
Скрипты, которые что-то меняют снаружи — файлы, базу, письма, сообщения, — отличаются от остального кода одним: ошибку нельзя откатить. Поэтому для них есть короткий список, который стоит применять всегда:
- Режим показа по умолчанию. Выполнение — по явному флагу.
- Сначала на копии.
cp -r photos photos-пробазанимает секунду. - Никогда не перезаписывать молча. Совпало имя — остановиться.
- Фильтр по типу. «Все файлы в папке» — почти никогда не то, что имелось в виду.
- Отчёт в конце. Сколько обработано, сколько пропущено и почему.
- Папка — аргумент, а не константа. Константу однажды забудут поменять.
Ни один пункт не требует усилий. Все шесть вместе — это разница между инструментом и рулеткой.
Шпаргалка
Самый опасный код — самый короткий: к нему не относятся серьёзно.
renameперезаписывает молча: два файла с одной датой — минус один файл.У скрипта, меняющего файлы, нет отмены. Ни истории, ни корзины.
Режим показа по умолчанию — главная защита, и стоит одну строку требований.
«Все файлы в папке» почти никогда не означает то, что ты имел в виду.
Первый запуск — на копии папки, а не на настоящей.
Шесть строк требований к девяти строкам кода — нормальная пропорция.