by By: Kerim in hddcleaner | python

I had the time do rework my hddcleaner a bit.
It's now ready to be shown.

Performance has increased dramatically.
Scanning my c and d drives and displaying the results on windows xp using python 2.5 takes now only around 31 seconds.
Memory usage for the task maxes at 77 MB. Tested on a two partition drive with a total of aound 40 GB (some 4-5GB free)

It does what it is supposed to do.

As a default it will look in all drives (windows) or root(unix). You may specify a folder or drive as command line parameter e.g. "HDDCleaner c:\mydrive"

Ok, here is a final version ready for download as exe, python source or simply copy paste from below.

What would be nice for the future is a feature to sort the columns in the frame and to limit the filetypes that are looked for.
Next version perhaps ;)


Exe-Version:


binary dependencies
Your executable(s) also depend on these dlls which are not included,
you may or may not need to distribute them.

Make sure you have the license if you distribute any of them, and
make sure you don't distribute files belonging to the operating system.

OLEAUT32.dll - C:WINDOWSsystem32OLEAUT32.dll
USER32.dll - C:WINDOWSsystem32USER32.dll
COMCTL32.dll - C:WINDOWSsystem32COMCTL32.dll
SHELL32.dll - C:WINDOWSsystem32SHELL32.dll
ole32.dll - C:WINDOWSsystem32ole32.dll
WINMM.dll - C:WINDOWSsystem32WINMM.dll
WSOCK32.dll - C:WINDOWSsystem32WSOCK32.dll
comdlg32.dll - C:WINDOWSsystem32comdlg32.dll
ADVAPI32.dll - C:WINDOWSsystem32ADVAPI32.dll
MSVCP71.dll - D:Programmierungpython25libsite-packageswx-2.8-msw-unicode
wxMSVCP71.dll
GDI32.dll - C:WINDOWSsystem32GDI32.dll
KERNEL32.dll - C:WINDOWSsystem32KERNEL32.dll
gdiplus.dll - D:Programmierungpython25libsite-packageswx-2.8-msw-unicode
wxgdiplus.dll
RPCRT4.dll - C:WINDOWSsystem32RPCRT4.dll


SourceVersion:
Needed is wxPython and win32api optional


Source for copy paste:

#!/usr/bin/env python  
# -*- coding: utf-8 -*-  
import sys, os, wx  
from wx.lib.mixins.listctrl import CheckListCtrlMixin  
from stat import *  

ID_DELETE=100  

def listDrives():  
    if sys.platform == 'win32':  
        try:  
            import win32api,string  
            drives=win32api.GetLogicalDriveStrings()  
            drives=string.splitfields(drives,'\000')  
            return drives  
        except: # in case PyWin is not present we do it the classical way  
            drives = []  
            for i in range(ord('a'), ord('z')+1):  
                drive = chr(i)  
                if(os.path.exists(drive +":\\")):  
                    drives.append(drive+":\\")  
            return drives  


def listFreeSpace(drive):  
    try:  
        if sys.platform == 'win32':  
            import win32api,string  
            info=win32api.GetDiskFreeSpaceEx(drive)  
            return info  
    except: # most probably pywin is not present  
        print "Unexpected error:", sys.exc_info()  

def listFilesByName(listOfFiles,directory,files):  
    for fileName in files:  
        filepath = os.path.join(directory,fileName)  
        if os.path.isfile(filepath):  
            filesize = os.stat(filepath)[ST_SIZE]  
            listOfFiles[filepath] = filesize  

def scan(directories):   
    listOfFiles = {}  
    for directory in directories:   
        sys.stdout.write('Scanning directory '+directory+'...\n')           
        directory = os.path.abspath(directory)  
        os.path.walk(directory,listFilesByName,listOfFiles)         
    sys.stdout.write('Done scanning all dirs. Now sorting and building GUI.\n')  
    allFiles = listOfFiles.items()  
    allFiles.sort(list_compare)  
    sortedList = allFiles  
    return sortedList  

def list_compare(listX, listY):  
    if listX[1]>listY[1]:  
        return -1  
    elif listX[1]==listY[1]:  
        return 0  
    else: # x<y  
        return 1  

class CheckListCtrl(wx.ListCtrl, CheckListCtrlMixin):  
    def __init__(self, parent):  
        wx.ListCtrl.__init__(self, parent, -1, style=wx.LC_REPORT)  
        CheckListCtrlMixin.__init__(self)  
        self.log = sys.stdout  
        self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnItemActivated)  

    def OnItemActivated(self, evt):  
        self.ToggleItem(evt.m_itemIndex)  

class FilesFrame(wx.Frame):       
    def __init__(self, parent, files):   
        wx.Frame.__init__(   
            self, parent, -1, "HDD Clean", size=(640,480)   
            )   
        p = wx.Panel(self, -1, style=0)   
        b = wx.Button(p, -1, "Delete...")   
        b.SetDefault()   
        self.Bind(wx.EVT_BUTTON, self.OnDelete, b)   
        self.files=files  
        self.list = CheckListCtrl(p)  
        sizer = wx.BoxSizer(wx.VERTICAL)  
        sizer.Add(b, 0, wx.EXPAND)  
        sizer.Add(self.list, 1, wx.EXPAND)  
        p.SetSizer(sizer)  

        self.list.InsertColumn(0, "Delete")  
        self.list.InsertColumn(1, "Size",wx.LIST_FORMAT_RIGHT)  
        self.list.InsertColumn(2, "File")  
        self.list.InsertColumn(3, "Type")  


        for i in self.files:  
            index = self.list.InsertStringItem(sys.maxint,"")  
            self.list.SetStringItem(index, 1, str(i[1]))  
            self.list.SetStringItem(index, 2, str(i[0]))  
            indexForFileType=str(i[0]).rfind(".")+1  
            filetype="None"  
            if indexForFileType!=0 and (len(str(i[0]))-indexForFileType<10):  
                filetype=str(i[0])[indexForFileType:]  
            self.list.SetStringItem(index, 3, filetype)  

        self.list.SetColumnWidth(0, wx.LIST_AUTOSIZE)  
        self.list.SetColumnWidth(1, wx.LIST_AUTOSIZE)  
        self.list.SetColumnWidth(2, wx.LIST_AUTOSIZE)  
        self.list.SetColumnWidth(3, wx.LIST_AUTOSIZE)  

        self.Show(1)  

    def OnDelete(self, evt):   
        items=self.list.GetItemCount()  
        allItems = range(0,items)  
        allItems.reverse()  
        for item in allItems:  
            if self.list.IsChecked(item):  
                listItem=self.list.GetItem(item,col=2)  
                self.list.DeleteItem(item)  
                os.remove(listItem.GetText())  

myapp=wx.PySimpleApp()  
files={}  
if len(sys.argv)>1:  
    files=scan(sys.argv[1:])  
else:  
    allDrives = listDrives()  
    if allDrives==None:  
        files = scan("/")  
    else:  
        files= scan(allDrives)  
if len(files)>0:  
    FilesFrame(None,files)  
    myapp.MainLoop()  
else:  
    print "No files found, exiting !"