Как автоматизировать удаление ненужных файлов с помощью Python 

Как автоматизировать удаление ненужных файлов с помощью Python 


Определение задач для автоматизации

Сначала требовалось определить задачи для автоматизации. По итогам вдумчивого анализа получился следующий перечень.

  • Удаление повторяющихся файлов, например файлов с похожими именами (img.pngimg(1).pngimg(2).png), и сохранение самой последней версии с одновременным удалением всех остальных.
  • Удаление временных файлов, в которых уже нет необходимости. К ним относятся: логи, скриншоты, кеш и установочные файлы.
  • Систематизация файлов в папке загрузок Downloads путем упорядочивания их по типу и перемещение файлов в специально обозначенные папки.
  • Удаление старых/неиспользуемых приложений, занимающих необходимое дисковое пространство. 

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

СКРИПТ РАЗБИТ НА ОТДЕЛЬНЫЕ ФРАГМЕНТЫ КОДА ДЛЯ КАЖДОЙ ЗАДАЧИ, ЧТОБЫ ОБЛЕГЧИТЬ НАСТРОЙКУ ПРОЦЕССА АВТОМАТИЗАЦИИ ПОД СВОИ НУЖДЫ. 

Удаление повторяющихся файлов 


Довольно часто я обнаруживаю скопления нескольких версий одного и того же файла (разных размеров), поскольку скачиваю/сохраняю файлы из интернета или приложения с одинаковым именем! 

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

import os
import re

def remove_duplicates(directory):
    for root, dirs, files in os.walk(directory):
        filedict = {}
        for filename in files:
            filepath = os.path.join(root, filename)

            # Проверяет, повторяется ли файл 
            match = re.search(r'^(.*?)\((\d+)\)(\.[^.]*)?$', filename)
            if match:
                name = match.group(1)
                number = int(match.group(2))
                ext = match.group(3) or ''

                # Добавление файла в словарь с именем в качестве ключа и числом в качестве значения 
                if name not in filedict:
                    filedict[name] = [(number, filepath, ext)]
                else:
                    filedict[name].append((number, filepath, ext))

        # Переименование файлов в каждой группе 
        for name in filedict:
            files = filedict[name]
            files.sort(key=lambda x: x[0])
            print(files)
            latest = files[-1][1]
            ext = files[-1][2]

            for number, filepath, _ in files[:-1]:
                print(f"Deleted duplicate file: {filepath}")
                os.remove(filepath)

            os.rename(latest, os.path.join(root, f"{name}{ext}"))
            print(f"Renamed {latest} to {name}{ext}")

remove_duplicates(os.path.expanduser("~/Downloads"))
ЕСЛИ ВЫ ИЩИТЕ СПОСОБ УДАЛЕНИЯ ФАЙЛОВ ОДИНАКОВОГО РАЗМЕРА ИЛИ СОДЕРЖАНИЯ, ТО ПЕРЕХОДИТЕ ЗА ИНТЕРЕСУЮЩЕЙ ИНФОРМАЦИЕЙ ПО УКАЗАННОЙ ССЫЛКЕ.

Удаление временных файлов 

Этот скрипт ищет временные файлы в таких директориях компьютера, как /private/var/folders~/Library/Caches~/Library/Logs~/Downloads и ~/Desktop, и удаляет те из них, что изрядно там подзадержались. 

Скрипт знает, что делать: он содержит список расширений файлов extensions, которые находит и удаляет. Точно также он поступает и со скриншотами, накапливающимися в директории ~/Desktop:

import os
import shutil

# Список директорий для поиска временных файлов
temp_directories = [
    '/private/var/folders',
    '~/Library/Caches',
    '~/Library/Logs',
    '~/Downloads',
    '~/Desktop'
]

# Список расширений файлов, подлежащих удалению 
extensions = [
    '.log',
    '.cache',
    '.tmp',
    '.dmg',
    '.pkg'
]

for directory in temp_directories:
    for dirpath, dirnames, filenames in os.walk(os.path.expanduser(directory)):
        for filename in filenames:
            # Проверяет, значится ли расширение файла в списке тех, что подлежат удалению 
            if os.path.splitext(filename)[1].lower() in extensions:
                filepath = os.path.join(dirpath, filename)
                try:
                    if os.path.isfile(filepath):
                        os.remove(filepath)
                    elif os.path.isdir(filepath):
                        shutil.rmtree(filepath)
                    print(f"Removed {filepath}")
                except Exception as e:
                    print(f"Error deleting {filepath}: {e}")
                    
    # Удаление скриншотов из директории Desktop
    if directory == '~/Desktop':
        desktop_path = os.path.expanduser(directory)  # expand ~ to home directory
        screenshot_files = [f for f in os.listdir(desktop_path) if f.startswith('Screenshot')]
        for file in screenshot_files:
            filepath = os.path.join(desktop_path, file)
            try:
                os.remove(filepath)
                print(f"Removed {filepath}")
            except Exception as e:
                print(f"Error deleting {filepath}: {e}")

Систематизация и удаление файлов в папке Downloads 

Содержимое моей папки Downloads напоминает ситуацию с пропавшими носками в сушилке — статус “утеряны безвозвратно”. Для поддержания порядка я систематизировала файлы по отдельным папкам в зависимости от их типа: изображения, видео, документы, аудио, код и даже файлы Photoshop:

Downloads/
├─ Image/
├─ Video/
│  ├─ Subtitle/
├─ Code/
├─ Document/
├─ Audio/
├─ Photoshop/

Созданный код также учитывает мою тягу к порядку и делает за меня всю грязную работу. Он распаковывает файлы .zip, удаляет файлы .torrent и даже перемещает файлы .srt в соответствующую папку. А вот и сам скрипт: 

import os
import shutil
import zipfile

downloads_dir = os.path.expanduser("~/Downloads")

# Создание словаря типов файлов и соответствующих им папок 
file_types = {
    "Image": [".jpg", ".jpeg", ".png", ".gif", ".tiff", ".bmp", ".eps"],
    "Code": [".ipynb",".py", ".js", ".html", ".css", ".php", ".cpp", ".h", ".java"],
    "Document": [".pdf", ".doc", ".docx", ".txt", ".rtf", ".xls", ".xlsx", ".ppt", ".pptx"],
    "Audio": [".mp3", ".wav", ".aac", ".ogg"],
    "Video": [".mp4", ".avi", ".mov", ".flv", ".wmv", ".mpeg"],
    "Photoshop": [".psd"],
}

# Создание папок для каждого типа файла 
for folder_name in file_types.keys():
    folder_path = os.path.join(downloads_dir, folder_name)
    if not os.path.exists(folder_path):
        os.makedirs(folder_path)

# Итерация по файлам в папке Downloads
for filename in os.listdir(downloads_dir):
    filepath = os.path.join(downloads_dir, filename)

# Распаковка и удаление файлов .zip 
    if filename.endswith(".zip"):
        # Проверяет, распакован ли файл 
        unzip_dir = os.path.join(downloads_dir, filename[:-4])
        if not os.path.exists(unzip_dir):
            # Распаковка файла .zip
            with zipfile.ZipFile(filepath, 'r') as zip_ref:
                zip_ref.extractall(downloads_dir)
        # Удаление файла .zip
        os.remove(filepath)
        print(f"Unzipped and removed {filename}")

    # Удаление файлов .torrent 
    elif filename.endswith(".torrent"):
        os.remove(filepath)
        print(f"Removed {filename}")

    # Перемещение файлов .srt в папку .subtitle внутри папки Video 
    elif filename.endswith(".srt"):
        dest_folder = os.path.join(downloads_dir, "Video", ".subtitle")
        if not os.path.exists(dest_folder):
            os.makedirs(dest_folder)
        shutil.move(filepath, os.path.join(dest_folder, filename))
        print(f"Moved {filename} to {dest_folder}")

    # Перемещение файла в соответствующую папку в зависимости от его расширения 
    else:
        for folder_name, extensions in file_types.items():
            if any(filename.endswith(ext) for ext in extensions):
                dest_folder = os.path.join(downloads_dir, folder_name)
                shutil.move(filepath, os.path.join(dest_folder, filename))
                print(f"Moved {filename} to {dest_folder}")
                break

Удаление старых/неиспользуемых приложений

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

import os
import subprocess
import time

# Определение количества дней бездействия приложения перед запросом на его удаление 
inactivity_period = 90 # 90 дней 

# Получение списка установленных приложений 
apps_dir = "/Applications"
app_names = os.listdir(apps_dir)

# Проверка времени последнего доступа для каждого бинарного файла приложения и запрос на его удаление при условии 90-дневного неактивного периода 
for app_name in app_names:
    app_path = os.path.join(apps_dir, app_name)
    if os.path.isdir(app_path):
        app_binary = os.path.join(app_path, "Contents/MacOS", app_name[:-4])
        if os.path.exists(app_binary):
            last_access_time = os.stat(app_binary).st_atime
            days_since_access = (time.time() - last_access_time) // (24 * 60 * 60)
            if int(days_since_access) > inactivity_period:
                alert_message = f"Are you still using {app_name}? Do you want to remove it?"
                button_pressed = subprocess.run(['osascript', '-e', f'tell app "System Events" to display alert "{alert_message}" buttons {{"Keep", "Remove"}} default button "Remove"', '-e', 'button returned of result'], stdout=subprocess.PIPE, encoding='utf-8').stdout.strip()
                if button_pressed == "Remove":
                    print(f"Removed {app_name}")
                    subprocess.run(['sudo', 'rm', '-rf', app_path])
                else:
                    print(f"Kept {app_name}")
                    with open('app_decisions.txt', 'a') as file:
                        file.write(f"{app_name},Keep,{time.time()}\n")
ПРИМЕЧАНИЕ. ДАННЫЙ СКРИПТ СЛЕДУЕТ ЗАДЕЙСТВОВАТЬ ТОЛЬКО ПРИ УСЛОВИИ ПОЛНОГО ПОНИМАНИЯ ЕГО ФУНКЦИОНАЛЬНЫХ ВОЗМОЖНОСТЕЙ И ПОТЕНЦИАЛЬНЫХ РИСКОВ. ОН РАЗРАБОТАН ДЛЯ УДАЛЕНИЯ СТАРЫХ И НЕИСПОЛЬЗУЕМЫХ ПРИЛОЖЕНИЙ, НО МОЖЕТ ПРИВЕСТИ К СЛУЧАЙНОМУ УДАЛЕНИЮ ВАЖНЫХ ПРИЛОЖЕНИЙ И ДАННЫХ. 

Планирование периодического выполнения скриптов 

Следующий этап после подготовки скриптов заключался в планировании их периодического выполнения. Это можно было сделать разными способами. Я же воспользовалась планировщиком cron для планирования запусков скриптов в системе Mac. Эта полезная утилита позволяет планировать выполнение задач через определенные промежутки времени. 

Я открыла файл crontab и добавила следующие записи: 

0 0 * * * /path/to/remove_dupes.py
0 0 * * * /path/to/remove_temps.py
0 5,17 * * * /path/to/download_cleanup.py
0 0 1 * * /path/to/remove_apps.py

Данные записи выполняют скрипты remove_dupes.py и remove_temps.py один раз в день. Скрипт download_cleanup.py  — дважды в день в 5:00 и 17:00, а скрипт remove_apps.py  — один раз в месяц в первый его день. 

Воспользовавшись сайтом crontab guru, вы сможете планировать периодичность выполнения задач в соответствии со своими потребностями. 

Перед планированием автоматического выполнения скриптов еще раз проверьте их и убедитесь, что они отвечают вашим целям. Каждый раз при автоматизации процессов будьте предельно внимательны, чтобы случайно не удалить что-то важное!


Перевод статьи Gargee SureshHow I Use Python To Clear Junk on My Laptop



Report Page