Search
Write a publication
Pull to refresh

Автоматическая сортировка файлов на Python: из хаоса в порядок одной командой

Level of difficultyEasy
Reading time7 min
Views3.7K

Привет, Хабр! Думаю, всем знакома ситуация: десятки файлов на рабочем столе, сваленных в единую кучу. Скрины, документы, архивы — и всё в одном рабочем пространстве. Наводить порядок не всегда получается, а жить в беспорядке не очень удобно. Недавно, в процессе наведения порядка, я утомился делать это руками и очень захотел написать скрипт на Python, который структурирует и раскидает всё по папкам самостоятельно.

Скрипт в статье:

  • Автоматически сортирует файлы по 9 категориям

  • Поддерживает 50+ форматов файлов

  • Предоставляет гибкие настройки

Введение

Начну с небольшой «демонстрации возможностей» скрипта. Работа со скриптом начинается с настройки конфига, где можно указать не только папку для сортировки, но и некоторые правила, такие как: создание подпапки по дате (полезно для скринов/фото), пропуск скрытых файлов, создание бэкапов, тестовый режим (покажет все действия без реального перемещения), а также возможность добавлять новые расширения и менять структуру сортировки. Всё это подкрепляется логированием.

Сам скрипт:

import os
import shutil
import argparse
from datetime import datetime

def setup_config():
    """Настройки по умолчанию с возможностью переопределения"""
    return {
        # Основные параметры
        'target_folder': os.path.expanduser("~/Desktop"),
        'log_file': os.path.expanduser("~/Desktop/sort_files.log"),
        'date_format': "%Y-%m-%d %H:%M:%S",
        
        # Правила сортировки (можно расширять, менять и тд.)
        'sort_rules': {
            "Images": [".jpg", ".jpeg", ".png", ".gif", ".webp", ".bmp", ".svg", ".tiff"],
            "Documents": [".pdf", ".docx", ".xlsx", ".pptx", ".txt", ".rtf", ".odt", ".csv"],
            "Archives": [".zip", ".rar", ".7z", ".tar", ".gz", ".bz2"],
            "Media": [".mp3", ".mp4", ".avi", ".mkv", ".mov", ".wav", ".flac"],
            "Code": [".py", ".js", ".html", ".css", ".json", ".xml", ".php", ".sh"],
            "Executables": [".exe", ".msi", ".dmg", ".pkg", ".deb"],
            "Design": [".psd", ".ai", ".sketch", ".fig"],
            "Data": [".sql", ".db", ".sqlite", ".mdb"],
            "Other": []  # Для нераспознанных расширений
        },
        
        # Дополнительные опции
        'create_date_folders': False,  # Создавать подпапки по дате
        'skip_hidden': True,           # Пропускать скрытые файлы
        'dry_run': False,              # Тестовый режим без реальных действий
        'backup_files': False          # Создавать копии перед перемещением
    }

def create_folders(target_folder, folders, dry_run=False):
    """Создание папки для категорий"""
    for folder in folders:
        path = os.path.join(target_folder, folder)
        if not dry_run:
            os.makedirs(path, exist_ok=True)
        else:
            print(f"[DRY RUN] Создана папка: {path}")

def get_file_category(filename, sort_rules):
    """Определение категории файла по его расширению"""
    ext = os.path.splitext(filename)[1].lower()
    for category, extensions in sort_rules.items():
        if ext in extensions:
            return category
    return "Other"

def backup_file(src, dest, dry_run=False):
    """Создание резервной копии файла перед перемещением"""
    backup_path = dest + ".backup"
    if not dry_run:
        shutil.copy2(src, backup_path)
    return backup_path

def sort_files(config):
    """Основная функция сортировки файлов"""
    target_folder = config['target_folder']
    sort_rules = config['sort_rules']
    folders = list(sort_rules.keys())
    
    # Создание лог-файла
    with open(config['log_file'], 'a') as log:
        log.write(f"\n=== Сортировка начата: {datetime.now().strftime(config['date_format'])} ===\n")
        
        # Создание необходимых папок
        create_folders(target_folder, folders, config['dry_run'])
        
        # Обработка файлов
        for item in os.listdir(target_folder):
            item_path = os.path.join(target_folder, item)
            
            # Пропуск папок и скрытых файлов (если включено)
            if not os.path.isfile(item_path):
                continue
            if config['skip_hidden'] and item.startswith('.'):
                continue
            
            # Определение категории
            category = get_file_category(item, sort_rules)
            
            # Формировка пути назначения
            dest_folder = os.path.join(target_folder, category)
            
            # Опционально: создание подпапки по дате
            if config['create_date_folders']:
                today = datetime.now().strftime("%Y-%m-%d")
                dest_folder = os.path.join(dest_folder, today)
                if not config['dry_run']:
                    os.makedirs(dest_folder, exist_ok=True)
            
            dest_path = os.path.join(dest_folder, item)
            
            # Логирование
            action = f"[+] {item} -> {category}"
            if config['create_date_folders']:
                action += f"/{today}"
            print(action)
            log.write(action + "\n")
            
            # Перемещение (или тестовый режим)
            if not config['dry_run']:
                # Создание резервной копии при необходимости
                if config['backup_files']:
                    backup_path = backup_file(item_path, dest_path)
                    log.write(f"  Создана резервная копия: {backup_path}\n")
                
                # Перемещение файла
                try:
                    shutil.move(item_path, dest_path)
                except Exception as e:
                    error_msg = f"Ошибка при перемещении {item}: {str(e)}"
                    print(error_msg)
                    log.write(error_msg + "\n")

def main():
    """Основная функция с обработкой аргументов командной строки"""
    parser = argparse.ArgumentParser(
        description="Скрипт для сортировки файлов на рабочем столе по категориям",
        epilog="Пример использования: python sort_desktop.py --target ~/Desktop --dry-run"
    )
    
    # Аргументы командной строки
    parser.add_argument('--target', help="Папка для сортировки (по умолчанию: Desktop)")
    parser.add_argument('--log', help="Файл для записи логов")
    parser.add_argument('--dry-run', action='store_true', help="Тестовый режим без реальных действий")
    parser.add_argument('--date-folders', action='store_true', help="Создавать подпапки по дате")
    parser.add_argument('--no-skip-hidden', action='store_true', help="Не пропускать скрытые файлы")
    parser.add_argument('--backup', action='store_true', help="Создавать резервные копии файлов")
    parser.add_argument('--show-config', action='store_true', help="Показать текущие настройки и выйти")
    
    args = parser.parse_args()
    
    # Загрузка конфигурации
    config = setup_config()
    
    # Переопределение настройки из аргументов
    if args.target:
        config['target_folder'] = os.path.expanduser(args.target)
    if args.log:
        config['log_file'] = os.path.expanduser(args.log)
    if args.dry_run:
        config['dry_run'] = True
    if args.date_folders:
        config['create_date_folders'] = True
    if args.no_skip_hidden:
        config['skip_hidden'] = False
    if args.backup:
        config['backup_files'] = True
    
    # Показ конфигурации (если нужно)
    if args.show_config:
        print("Текущие настройки:")
        for key, value in config.items():
            print(f"  {key}: {value}")
        return
    
    # Запуск сортировки
    print("=== Начало сортировки ===")
    print(f"Целевая папка: {config['target_folder']}")
    print(f"Режим dry-run: {'да' if config['dry_run'] else 'нет'}")
    
    sort_files(config)
    
    print("\n=== Сортировка завершена ===")
    print(f"Подробности в лог-файле: {config['log_file']}")

if __name__ == "__main__":
    main()

Структура скрипта

Скрипт состоит из нескольких ключевых функций:

  1. setup_config() - инициализация настроек по умолчанию

  2. create_folders() - создание папок для категорий

  3. get_file_category() - определение категории файла по расширению

  4. backup_file() - создание резервной копии файла

  5. sort_files() - основная функция сортировки

  6. main() - обработка аргументов командной строки и запуск процесса

Настройка конфигурации

Функция setup_config() возвращает словарь с настройками:

{
    'target_folder': "~/Desktop",  # Папка для сортировки
    'log_file': "~/Desktop/sort_files.log",  # Файл для логов
    'date_format': "%Y-%m-%d %H:%M:%S",  # Формат даты в логах
    
    # Правила сортировки по расширениям
    'sort_rules': {
        "Images": [".jpg", ".jpeg", ".png", ...],
        "Documents": [".pdf", ".docx", ".xlsx", ...],
    },
    
    # Дополнительные опции
    'create_date_folders': False,  # Создавать подпапки по дате
    'skip_hidden': True,           # Пропускать скрытые файлы
    'dry_run': False,              # Тестовый режим
    'backup_files': False          # Создавать копии файлов
}

Алгоритм работы

  1. Инициализация: загрузка конфигурации, обработка аргументов командной строки

  2. Подготовка: создание папок для всех категорий из sort_rules

  3. Обработка файлов:

    • Для каждого файла в целевой папке определяется категория

    • Формируется путь назначения (с учетом подпапок по дате при необходимости)

    • Создается резервная копия (если включено)

    • Файл перемещается в соответствующую папку

  4. Логирование: все действия записываются в лог-файл

Обработка аргументов командной строки

Скрипт использует модуль argparse для гибкой настройки:

parser = argparse.ArgumentParser(
    description="Скрипт для сортировки файлов на рабочем столе по категориям",
    epilog="Пример использования: python sort.py --target ~/Desktop --dry-run"
)

parser.add_argument('--target', help="Папка для сортировки (по умолчанию: Desktop)")
parser.add_argument('--log', help="Файл для записи логов")
parser.add_argument('--dry-run', action='store_true', help="Тестовый режим без реальных действий")

Это позволяет легко изменять поведение скрипта без редактирования кода.

Пример и демонстрация использования

Для демонстрации наведу искусственный беспорядок на рабочем столе:

До запуска скрипта
До запуска скрипта

И, командой в cmd (python sort.py - базовая сортировка) запустим скрипт. Результат:

После запуска скрипта
После запуска скрипта

А также, можем заглянуть в файл лога:

Log
Log

Далее, стоит рассмотреть остальные варианты команд. Начнём с тестового запуска для проверки (python sort.py --dry-run):

Тестовый запуск
Тестовый запуск

В данном случае, все наши файлы остались на месте. Данная команда нужна больше для настройки, чтобы ничего случайно не потерять. Далее, рассмотрим сортировку по дате (python sort.py --date-folders):

Сортировка по дате
Сортировка по дате

Папки остались всё те же, но в них появились подпапки с меткой по дате. Выглядит это следующим образом:

Пример результата сортировки по дате
Пример результата сортировки по дате

Аналогично всем инструментам, есть поддержка продвинутых сценариев, пару примеров которых я приведу:

# Сортировка с резервными копиями и подпапками по дате
python sort.py --backup --date-folders

# Тестовый прогон для папки "Загрузки"
python sort.py --target ~/Downloads --dry-run

Заключение

Представленный в статье скрипт — хорошее решение для тех, кто устал от хаоса на рабочем столе. Он не требует глубоких знаний Python для использования и настройки, но предлагает достаточно широкий функционал по сортировке.

Хочу спросить у сообщества:

  • Какие функции вы бы добавили в подобный инструмент?

  • Интересна ли вам версия с графическим интерфейсом?

  • Стоит ли развивать это решение в полноценный набор инструментов для автоматизации рутины?

Спрашиваю из-за желания изучить создание ПО. В процессе написания скрипта подумал, что добавление GUI/шаблонов/тегов в данном решении смотрелись бы отлично. Да, возможно скрипт не найдет широкого применения и по большей части для многих будет бесполезен, но не поделиться им не мог. Он решил мою вечную проблему свалки.

P.S. Я веду свою группу в Телеграмм, буду рад видеть всех, кому интересен процесс написания скриптов и автоматизация в мире IT.

Tags:
Hubs:
+6
Comments5

Articles