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

Представьте такую ситуацию: вам нужно найти один файл, скаченный неделю назад, и сделать это быстро. Но вместо этого вы наталкиваетесь на беспорядочное нагромождение файлов в папке загрузок. Звучит знакомо? Я оказалась как раз в такой ситуации, и мне было не до смеха. Нужно было что-то предпринять, чтобы не стать жертвой надвигающегося бардака. 

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

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

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

  • Удаление повторяющихся файлов, например файлов с похожими именами (img.png, img(1).png, img(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, вы сможете планировать периодичность выполнения задач в соответствии со своими потребностями. 

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

Читайте также:

Читайте нас в TelegramVK и Дзен


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

Предыдущая статьяПредставление концепций ООП с реальными сценариями
Следующая статьяКак реализовать функциональность перетаскивания с помощью React Beautiful Dnd