Скрипт на Python для автосортировки папки «Загрузки»: готовый код и автозапуск
Содержание гайда
Папка «Загрузки» (Downloads) на рабочем компьютере почти всегда превращается в цифровую свалку. Туда стекаются торренты, временные архивы, установочные дистрибутивы, скриншоты, сканы паспортов и рабочие PDF-отчеты. Когда внутри скапливается более пятисот файлов, поиск нужного документа превращается в пытку, а ручная сортировка отнимает драгоценное время.
Ниже представлен полноценный скрипт на Python, не требующий сторонних библиотек (работает на чистых встроенных модулях os, shutil, pathlib, logging, time). Он умеет:
- Автоматически раскладывать файлы по категориям (
Документы,Изображения,Видео,Архивы,Программы,Аудио,Торренты,Код и Скрипты). - Игнорировать незавершенные скачивания браузеров (
.crdownload,.part,.tmp,.download). - Корректно разрешать конфликты имен: если файл
report.pdfуже есть в целевой папке, скрипт автоматически переименует копию вreport_1.pdf, а не затрет исходник. - Вести локальный лог-файл всех перемещений (
organizer.log). - Работать в двух режимах: разовый прогон или фоновый непрерывный мониторинг раз в N секунд.
1. Исходный код скрипта organizer.py
Создайте файл organizer.py в любой удобной папке (например, C:\Scripts\organizer.py или ~/scripts/organizer.py) и скопируйте в него этот код:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import shutil
import time
import logging
from pathlib import Path
# ================= КОНФИГУРАЦИЯ =================
# Путь к папке загрузок (по умолчанию берется домашний каталог текущего пользователя)
DOWNLOADS_DIR = Path.home() / "Downloads"
# Лог-файл для аудита перемещений
LOG_FILE = DOWNLOADS_DIR / "organizer.log"
# Словарь сопоставления папок и расширений (в нижнем регистре)
EXTENSION_MAP = {
"Изображения": {
".jpg", ".jpeg", ".png", ".gif", ".bmp", ".svg", ".webp", ".ico", ".tiff", ".raw", ".heic"
},
"Документы": {
".pdf", ".docx", ".doc", ".txt", ".rtf", ".odt", ".xlsx", ".xls", ".csv", ".pptx", ".ppt"
},
"Архивы": {
".zip", ".rar", ".7z", ".tar", ".gz", ".bz2", ".xz", ".iso"
},
"Программы": {
".exe", ".msi", ".apk", ".deb", ".rpm", ".dmg", ".pkg", ".appimage"
},
"Видео": {
".mp4", ".mkv", ".avi", ".mov", ".wmv", ".flv", ".webm", ".m4v"
},
"Аудио": {
".mp3", ".wav", ".flac", ".aac", ".ogg", ".m4a", ".wma"
},
"Торренты": {
".torrent"
},
"Код и Скрипты": {
".py", ".go", ".js", ".ts", ".html", ".css", ".json", ".xml", ".yaml", ".yml", ".sh", ".bat"
}
}
# Временные расширения, которые нельзя трогать (идет процесс загрузки браузером)
IGNORED_EXTENSIONS = {".crdownload", ".part", ".tmp", ".download"}
# Имена файлов/папок, которые скрипт не должен перемещать
IGNORED_NAMES = {"organizer.log", "desktop.ini", ".DS_Store"}
IGNORED_NAMES.update(EXTENSION_MAP.keys())
IGNORED_NAMES.add("Другое")
# ================= НАСТРОЙКА ЛОГИРОВАНИЯ =================
logging.basicConfig(
filename=str(LOG_FILE),
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s",
encoding="utf-8"
)
def get_destination_folder(file_path: Path) -> Path:
ext = file_path.suffix.lower()
for folder_name, extensions in EXTENSION_MAP.items():
if ext in extensions:
return DOWNLOADS_DIR / folder_name
return DOWNLOADS_DIR / "Другое"
def resolve_duplicate_name(destination_folder: Path, file_name: str) -> Path:
stem = Path(file_name).stem
suffix = Path(file_name).suffix
target_path = destination_folder / file_name
counter = 1
while target_path.exists():
new_name = f"{stem}_{counter}{suffix}"
target_path = destination_folder / new_name
counter += 1
return target_path
def process_file(file_path: Path):
if not file_path.is_file():
return
file_name = file_path.name
# Пропуск системных и скрытых файлов
if file_name in IGNORED_NAMES or file_name.startswith("."):
return
ext = file_path.suffix.lower()
if ext in IGNORED_EXTENSIONS:
return
# Защита от блокировки: если размер файла все еще меняется (идет запись на диск)
try:
initial_size = file_path.stat().st_size
time.sleep(0.5)
if file_path.stat().st_size != initial_size:
return # Файл еще докачивается, пропустим до следующего цикла
except Exception:
return
dest_folder = get_destination_folder(file_path)
dest_folder.mkdir(parents=True, exist_ok=True)
target_path = resolve_duplicate_name(dest_folder, file_name)
try:
shutil.move(str(file_path), str(target_path))
log_msg = f"Перемещен: '{file_name}' -> '{dest_folder.name}/{target_path.name}'"
print(log_msg)
logging.info(log_msg)
except Exception as err:
error_msg = f"Ошибка перемещения '{file_name}': {err}"
print(error_msg)
logging.error(error_msg)
def run_organizer_once():
print(f"[*] Сканирование папки: {DOWNLOADS_DIR}")
for item in DOWNLOADS_DIR.iterdir():
if item.is_file():
process_file(item)
print("[+] Сканирование завершено.")
def run_organizer_daemon(interval_seconds: int = 30):
print(f"[*] Демон запущен. Мониторинг {DOWNLOADS_DIR} каждые {interval_seconds} сек. (Ctrl+C для выхода)")
try:
while True:
for item in DOWNLOADS_DIR.iterdir():
if item.is_file():
process_file(item)
time.sleep(interval_seconds)
except KeyboardInterrupt:
print("\n[!] Работа демона остановлена пользователем.")
if __name__ == "__main__":
# Запуск в режиме непрерывного фонового демона каждые 30 секунд
run_organizer_daemon(interval_seconds=30)
2. Пошаговый запуск и проверка
- Откройте командную строку или PowerShell:
cd C:\Scripts
python organizer.py
- Скрипт мгновенно создаст папки в ваших
Загрузках, разложит существующие файлы и будет ожидать появления новых каждые 30 секунд. - Скачайте тестовую картинку из браузера — в течение полуминуты она переместится в каталог
Downloads/Изображения.
3. Настройка тихого автозапуска при старте Windows
Чтобы терминал не мозолил глаза при старте компьютера:
Через Планировщик заданий (Task Scheduler)
- Переименуйте
organizer.pyвorganizer.pyw(расширение.pywговорит Windows запускать скрипт без создания черного окна консоли). - Нажмите
Win + R, введитеtaskschd.mscи нажмите Enter. - В правом меню выберите «Создать простую задачу»:
- Имя:
Downloads Cleaner - Триггер: «При входе в Windows»
- Действие: «Запустить программу»
- Программа или сценарий: выберите
pythonw.exe(путь:C:\Users\ВашеИмя\AppData\Local\Programs\Python\Python312\pythonw.exe). - Аргументы: укажите путь к файлу в кавычках:
"C:\Scripts\organizer.pyw".
- Имя:
- Нажмите «Готово». Теперь сортировка работает незаметно в фоновом режиме.
4. Настройка на сервере Linux / macOS (systemd unit)
Создайте юнит sudo nano /etc/systemd/system/downloads-cleaner.service:
[Unit]
Description=Auto Downloads Organizer
After=network.target
[Service]
Type=simple
User=youruser
ExecStart=/usr/bin/python3 /home/youruser/scripts/organizer.py
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
Активируйте службу:
sudo systemctl daemon-reload
sudo systemctl enable --now downloads-cleaner.service
Частые вопросы
❓ Не удалит ли скрипт файлы с одинаковыми именами?
Скрипт проверяет наличие дубликатов и добавляет числовой суффикс (1, 2, 3), предотвращая перезапись.
❓ Что происходит с временными файлами скачивания?
Расширения .crdownload, .part и .tmp внесены в черный список и игнорируются до завершения скачивания.
❓ Как запустить скрипт в скрытом режиме без черного окна консоли?
В Windows сохраните файл с расширением .pyw вместо .py — тогда он запустится через pythonw.exe без открытия терминала.