Массовое переименование и сортировка файлов
Разложить хаос из сотен файлов по аккуратным папкам — классическая задача автоматизации. Главное здесь — сначала рассчитать новые имена, и только потом трогать диск.
Суть: переименование = построить новое имя из старого по правилу. Сначала проверьте план на конфликты, потом примените черезrenameилиshutil.move.
Допустим, фотограф сбросил тысячу файлов IMG_3481.jpg, а нужно получить 2026-06-22_отпуск_001.jpg. Или бухгалтер хочет разложить счета по папкам-месяцам. Суть одинакова: для каждого файла мы вычисляем новое имя или новую папку по правилу, а затем перемещаем.
Самое важное — разделить план и исполнение. Сначала постройте словарь «старое имя → новое имя» и проверьте его: нет ли коллизий, когда два файла претендуют на одно имя. И только потом применяйте изменения. Так вы не испортите данные на середине процесса.
Логику построения имён и проверки коллизий можно полностью отработать в браузере — это чистые строки и словари.
Попробуй сам ▶
# План переименования: фото по дате и порядковому номеру
old_names = ['IMG_3481.jpg', 'IMG_3482.jpg', 'IMG_3483.jpg']
date = '2026-06-22'
label = 'otpusk'
plan = {}
for i, old in enumerate(sorted(old_names), start=1):
ext = old.split('.')[-1]
new = f'{date}_{label}_{i:03d}.{ext}'
plan[old] = new
# Проверка коллизий: новых имён должно быть столько же, сколько файлов
targets = list(plan.values())
if len(set(targets)) != len(targets):
print('ОШИБКА: есть дубли имён, переименование отменено')
else:
for old, new in plan.items():
print(f'{old} -> {new}')Формат {i:03d} печатает число с ведущими нулями: 1 превращается в 001. Это гарантирует правильную сортировку файлов — иначе file10 встанет раньше file2.
Когда план проверен, исполнение тривиально. Этот фрагмент трогает диск, поэтому он нерабочий в браузере.
from pathlib import Path
import shutil
folder = Path('photos')
for old, new in plan.items():
src = folder / old
dst = folder / new
if dst.exists(): # не затираем существующий файл
print('Пропуск:', new)
continue
src.rename(dst) # переименование в той же папке
# Перемещение в подпапку по месяцу:
month_dir = folder / '2026-06'
month_dir.mkdir(exist_ok=True)
shutil.move(str(folder / new), str(month_dir / new))БЕЗОПАСНОЕ ПЕРЕИМЕНОВАНИЕ
[1] собрать план -> словарь old -> new
|
[2] проверить -> нет коллизий? цел?
|
[3] применить -> rename / move
|
[4] лог -> что и куда переехало
Никогда не пропускай шаг [2].Отдельного внимания заслуживает режим «сухого прогона» (dry-run) — приём, который профессионалы применяют к любой массовой операции с файлами. Идея проста: добавьте в скрипт флаг, при котором он не выполняет действия, а лишь печатает, что собирается сделать. Прогнали с флагом, глазами проверили список переименований, убедились, что логика верна — и только потом запустили «по-настоящему». Этот лишний шаг занимает секунды, но именно он отделяет аккуратного инженера от того, кто однажды одной командой перемешал тысячу важных файлов без возможности откатиться.
Как работает под капотом
Path.rename и os.rename на уровне ОС — это почти мгновенная операция: меняется только запись в каталоге, сами байты файла не двигаются. Но это работает лишь в пределах одного диска. shutil.move умнее: если источник и приёмник на разных дисках, он физически копирует файл, а затем удаляет оригинал.
mkdir(exist_ok=True) создаёт папку, но не падает, если она уже есть — это делает скрипт идемпотентным: повторный запуск не вызовет ошибку «папка существует».
Частые ошибки
- Переименовывать без проверки коллизий. Два файла с одинаковым новым именем — и один безвозвратно затрёт другой.
- Менять файлы прямо в цикле обхода. Изменение папки во время её перебора ведёт к пропускам. Сначала соберите список, потом действуйте.
- Забывать ведущие нули. Без них сортировка по имени ломается на числах.
Best practices
- Сначала постройте и распечатайте план (dry-run), убедитесь глазами, потом применяйте.
- Проверяйте
dst.exists()перед перемещением, чтобы не затирать данные. - Логируйте каждое действие — при ошибке вы будете знать, где остановились.
Итоги. Массовое переименование — это план плюс исполнение: построить имена, проверить коллизии, применить через rename или move. Идемпотентность и dry-run спасают данные. Дальше разберём, как делать резервные копии перед опасными операциями.