Не ищем легких путей: пишем свою программу для чистки переполненного диска C: на Python

в 0:57, , рубрики: Без рубрики

Не ищем легких путей: пишем свою программу для чистки переполненного диска C: на PythonОчередное обновление Windows раздуло систему на 600 Мб. На диске С: из 100 Гб осталось последних свободных 300 Мб. В папке Downloads больших файлов не осталось, а очистка кешей и временных файлов через программу CCleaner спасает на неделю. Пришла пора глобальной чистки системы. За 2 года Windows оброс кучей ненужных файлов, которые нужно найти и удалить. Размер файла стал основным критерием поиска. Я решил вручную просмотреть все файлы более 50 Мб. Если бы это был Линукс, то хватило бы команды:

find / -type f | xargs du -sh | sort -n | tail -50

Но в Линуксе такой проблемы с местом и не возникло бы. Для Windows существует много готовых утилит, даже расширенного поиска Total Commander хватило бы для данной задачи. Но я решил не искать легких путей и за 30 минут все сделать своими руками на Python.

Код первой версии программы был необычайно прост:

import os

def searchBigFiles(path, bigSize):    
    folder=os.listdir(path)
    if path=='\':
        path=''
    for element in folder:
        if os.path.isfile(path+'\'+element):
            statinfo=os.stat(path+'\'+element)
            if(statinfo.st_size>1024*1024*bigSize):
                size=round(statinfo.st_size/(1024*1024),1)
                print(str(size)+' Mb - '+path+'\'+element)
        elif os.path.isdir(path+'\'+element):
            searchBigFiles(path+'\'+element, bigSize)
                
searchBigFiles('\xampp', 5)

Программа выводит на экран все файлы более 5 Мб, которые находятся в папке «xxamp». Скрипт сработал без ошибок. Но в корне диска C: он выдал ошибку:

PermissionError: [WinError 5] Отказано в доступе: '\Documents and Settings\*.*'

Запуская файл от имени Администратора, программа оказалась не защищена от таких ошибок:

  • PermissionError — ошибка сработала для 89 папок из 85984 просмотренных. Связана она с тем, что часть папок таких как «Documents and Settings» на самом деле не существуют, хотя os.path.isdir для них возвращает True.
  • FileNotFoundError — сработала только для файла программы Evernote.

Дописав блок try-catch, получили код, который смог проверить весь диск C: без ошибок:

import os

def searchBigFiles(path, bigSize):    
    try:
        folder=os.listdir(path)
        if path=='\':
            path=''
        for element in folder:
            if os.path.isfile(path+'\'+element):
                statinfo=os.stat(path+'\'+element)
                if(statinfo.st_size>1024*1024*bigSize):
                    size=round(statinfo.st_size/(1024*1024),1)
                    print(str(size)+' Mb - '+path+'\'+element)
            elif os.path.isdir(path+'\'+element):
                searchBigFiles(path+'\'+element, bigSize)
    except PermissionError:
        print('no access to folder: '+path)       
    except FileNotFoundError:
        print('folder doesn't exist: '+path)       
                
searchBigFiles('\', 100)

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

import os

class CleanDiskC:

    total=0;
    countFiles=0;
    countFolders=0;
    fileNotFoundError=list()
    permissionError=list()
    files=list()

    def __init__(self, bigSize=50, state=True):
        self.bigSize=bigSize
        self.stateless=state

    def printRow(self, size, path):
        size=str(size)+'Mb'
        while(len(size)<8):
            size+=' '
        print('|| '+size+'|| '+path)
    
    def findBigFiles(self, path):
        if not self.stateless:
            print('Progress: |', end='')
        self.searchBigFiles(path)       
        if not self.stateless:
            if len(self.fileNotFoundError)>0:
                print('nnCan't find files:')
                print('----------------------------')
                for elem in self.fileNotFoundError:
                    print(elem)
                print('----------------------------')
                print('Total: '+str(len(self.fileNotFoundError))+' elementsn')
            if len(self.permissionError)>0:
                print('nnDon't have pernission to access folder:')
                print('----------------------------')
                for elem in self.permissionError:
                    print(elem)
                print('----------------------------')
                print('Total: '+str(len(self.permissionError))+' foldersn')
            print('nFiles with size more then '+str(self.bigSize)+'Mb:')
            print('----------------------------')
            self.files.sort(key=lambda x: x['size'], reverse=True)
            for elem in self.files:
                self.printRow(elem['size'], elem['path'])
        print('----------------------------')
        print('Total big files store: '+str(round(self.total/1024,1))+'Gb')
        print('Total cheched: '+str(self.countFiles)+' files')
        print('Total checked: '+str(self.countFolders)+' folders')
            
        
    def searchBigFiles(self, path):
        self.countFolders+=1        
        try:
            folder=os.listdir(path)
            if path=='\':
                path=''
            for element in folder:
                if os.path.isfile(path+'\'+element):
                    self.countFiles+=1
                    if not self.stateless:
                        if self.countFiles%10000==0:
                            print(str(self.countFiles)+'|',end='')
                    statinfo=os.stat(path+'\'+element)
                    if(statinfo.st_size>1024*1024*self.bigSize):
                        size=round(statinfo.st_size/(1024*1024),1)
                        self.total+=size
                        if self.stateless:
                            self.printRow(size, path+'\'+element)
                        else:
                            self.files.append({'size':size, 'path':path+'\'+element})
                elif os.path.isdir(path+'\'+element):           
                        self.searchBigFiles(path+'\'+element)
        except PermissionError:
            if self.stateless:
                print('no access to folder: '+path)
            else:
                self.permissionError.append(path)
        except FileNotFoundError:
            if self.stateless:
                print('folder doesn't exist: '+path)
            else:
                self.fileNotFoundError.append(path)

#bigSize: default=50Mb
#stateless: default=True
            
do=CleanDiskC(50, False)
do.findBigFiles('\')

Закончив скрипт, я вернулся к первоначальной задаче и занялся диском. В корзину ушло:

  • .Trash-1000 — странным образом в корне диска C: оказалась скрытая папка Линукса с фильмом «Джанго освобожденный» — 2,5 Гб
  • виртуальная машина VirtualBox со снапшотами — 5 Гб
  • бэкапы iPad, iPhone (в настройках iTunes был указан другой диск) — 7 Гб
  • затерянные ранее загруженные файлы — 2 Гб
  • файлы проектов обработки видео — 10 Гб

Получилось безболезненно освободить 27 Гб. Такой подход позволил подробнее ознакомится с файлами операционной системой Windows и их взаимодействием с языком программирования Python.

Автор: coolweb

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js