Не ищем легких путей: пишем свою программу для чистки переполненного диска 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('\n\nCan\'t find files:')                 print('----------------------------')                 for elem in self.fileNotFoundError:                     print(elem)                 print('----------------------------')                 print('Total: '+str(len(self.fileNotFoundError))+' elements\n')             if len(self.permissionError)>0:                 print('\n\nDon\'t have pernission to access folder:')                 print('----------------------------')                 for elem in self.permissionError:                     print(elem)                 print('----------------------------')                 print('Total: '+str(len(self.permissionError))+' folders\n')             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.

ссылка на оригинал статьи http://habrahabr.ru/post/212421/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *