今天用wxPython做了一个GUI程序,我称之为UNIQ File,实现查找指定目录内的相同文件,主要原理是计算文件的md5值(计算前先找出文件大小相同的文件,然后计算这些文件的md5值,而不是所有文件都计算,大大减少了md5的计算量),加入了多线程功能。

运行该程序需要安装wxPython。

界面图

源代码:

UNIQFile-wxPython.py

 # -*- coding: gbk -*-

 '''
Author:@DoNotSpyOnMe
Blog: http://www.cnblogs.com/aaronhoo
''' import wx
import hashlib
import os
import threading class WorkerThread(threading.Thread):
def __init__(self, frame,dir,operation,msg):
"""初始化工作线程: 把主窗口传进来"""
threading.Thread.__init__(self)
self.frame = frame
self.dir=dir
self.operation=operation
self.msg=msg
self.setDaemon(True)#设置子线程随UI主线程结束而结束
self.start() #----------------------------------------------------------------------
def run(self):
"""执行工作线程"""
self.frame.SetButtons('operating')
try:
if self.operation=='list':
self.listSameFile(self.dir)
self.frame.btnList.Enable()
elif self.operation=='remove':
self.removeSameFile(self.dir)
self.frame.btnRemove.Enable()
except:
pass
finally:
self.frame.SetButtons('completed')
#
# def stop(self):
# self.keepRunning=False
def appendMsg(self,msg):
if self.frame:
#以下方式可以实现终端式的刷新:自动滚动到最新行
self.frame.txtContent.AppendText(msg+'\n')
#废弃的方式
# currentMsg=self.frame.txtContent.GetValue()
# currentMsg=currentMsg+'\n'+msg
# self.frame.txtContent.SetValue(currentMsg) def getFileSize(self,filePath):
return os.path.getsize(filePath) ''' 一般文件的md5计算方法,一次读取文件的全部内容'''
def CalcMD5(self,filepath):
with open(filepath,'rb') as f:
md5obj = hashlib.md5()
md5obj.update(f.read())
hash = md5obj.hexdigest()
return hash
'''大文件计算md5的方法,分批读取文件内容,防止内存爆掉'''
def GetFileMd5(self,filename):
if not os.path.isfile(filename):
return
myhash = hashlib.md5()
f = open(filename,'rb')
while True:
b = f.read(8*1024)
if not b :
break
myhash.update(b)
f.close()
return myhash.hexdigest() def GetAllFiles(self,directory):
files=[]
for dirpath, dirnames,filenames in os.walk(directory):
if filenames!=[]:
for file in filenames:
files.append(dirpath+'\\'+file)
       files.sort(key=len)#按照文件名的长度排序 
return files def findSameSizeFiles(self,files):
dicSize={}
for f in files:
size=self.getFileSize(f)
if not dicSize.has_key(size):
dicSize[size]=f
else:
dicSize[size]=dicSize[size]+';'+f
dicCopy=dicSize.copy()
for k in dicSize.iterkeys():
if dicSize[k].find(';')==-1:
dicCopy.pop(k)
del dicSize
return dicCopy def findSameMD5Files(self,files):
dicMD5={}
for f in files:
self.appendMsg('calculating the md5 value of file %s'%f)
md5=self.GetFileMd5(f)
if not dicMD5.has_key(md5):
dicMD5[md5]=f
else:
dicMD5[md5]=dicMD5[md5]+';'+f
dicCopy=dicMD5.copy()
for k in dicMD5.iterkeys():
if dicMD5[k].find(';')==-1:
dicCopy.pop(k)
del dicMD5
return dicCopy def removeSameFile(self,mydir):
msg=''
msgUniq='Congratulations,no file is removed since they are all uniq.'
try:
existsFlag=False
files=self.GetAllFiles(mydir)
self.appendMsg('%s files found in directory %s\n'%(len(files),mydir))
dicFileOfSameSize=self.findSameSizeFiles(files)
if dicFileOfSameSize=={}:
self.appendMsg(msgUniq)
return
else:
#list the duplicated files first:
dicFiltered={}
for k in dicFileOfSameSize.iterkeys():
filesOfSameSize=dicFileOfSameSize[k].split(';')
dicSameMD5file=self.findSameMD5Files(filesOfSameSize)
if dicSameMD5file!={}:
existsFlag=True
for k in dicSameMD5file.iterkeys():
msg=msg+'md5 %s: %s'%(k,dicSameMD5file[k])+'\n'
dicFiltered[k]=dicSameMD5file[k]
if not existsFlag:
msg=msgUniq
return
else:
msg='Duplicated files:\n'+msg+'\n'
#then remove the duplicated files:
removeCount=0
for k in dicFiltered.iterkeys():
sameFiles=dicFiltered[k].split(';')
flagRemove=False
for f in sameFiles:
if not flagRemove:
flagRemove=True
else:
msg=msg+'Removing file: %s'%f+'\n'
os.remove(f)
removeCount=removeCount+1
msg=msg+'%s files are removed.\n'%removeCount
except Exception,e:
# print e
msg='Exception occured.'
finally:
self.appendMsg(msg+'\n'+'Operation finished.') def listSameFile(self,mydir):
msg=''
msgUniq='Congratulations,all files are uniq.'
try:
existsFlag=False
files=self.GetAllFiles(mydir)
self.appendMsg('%s files found in directory %s\n'%(len(files),mydir))
dicFileOfSameSize=self.findSameSizeFiles(files)
if dicFileOfSameSize=={}:
self.appendMsg(msgUniq)
return
else:
for k in dicFileOfSameSize.iterkeys():
filesOfSameSize=dicFileOfSameSize[k].split(';')
dicSameMD5file=self.findSameMD5Files(filesOfSameSize)
if dicSameMD5file!={}:
existsFlag=True
for k in dicSameMD5file.iterkeys():
msg=msg+'md5 %s: %s'%(k,dicSameMD5file[k])+'\n'
if not existsFlag:
msg=msgUniq
else:
msg='Duplicated files:\n'+msg
except Exception,e:
# print e
msg='Exception occured.'
finally:
self.appendMsg(msg+'\n'+'Operation finished.') class MyFrame(wx.Frame):
def __init__(self):
super(MyFrame,self).__init__(None,title='UNIQ File-wxPython',size=(780,450))
pan=wx.Panel(self)
self.lblDir=wx.StaticText(pan,-1,'Dir:',style=wx.ALIGN_LEFT)
self.txtFile=wx.TextCtrl(pan,size=(380,30))
# self.txtFile.Disable()
self.btnOpen=wx.Button(pan,label='Pick Directory')
self.btnOpen.Bind(wx.EVT_BUTTON, self.BtnOpenHandler)
self.btnList=wx.Button(pan,label='Find Same')
self.btnList.Bind(wx.EVT_BUTTON, self.BtnListHandler)
self.btnRemove=wx.Button(pan,label='Remove duplicated')
self.btnRemove.Bind(wx.EVT_BUTTON, self.BtnRemoveHandler)
# self.btnStop=wx.Button(pan,label='Stop')
# self.btnStop.Bind(wx.EVT_BUTTON, self.BtnStopHandler) hbox=wx.BoxSizer()
hbox.Add(self.lblDir,proportion=0,flag=wx.LEFT,border=5)
hbox.Add(self.txtFile,proportion=0,flag=wx.LEFT,border=5)
hbox.Add(self.btnOpen,proportion=0,flag=wx.LEFT,border=5)
hbox.Add(self.btnList,proportion=0,flag=wx.LEFT,border=5)
hbox.Add(self.btnRemove,proportion=0,flag=wx.LEFT,border=5)
# hbox.Add(self.btnStop,proportion=0,flag=wx.LEFT,border=5) self.txtContent=wx.TextCtrl(pan,style=wx.TE_MULTILINE|wx.HSCROLL)
vbox=wx.BoxSizer(wx.VERTICAL)
vbox.Add(hbox,proportion=0,flag=wx.EXPAND|wx.ALL,border=5)
vbox.Add(self.txtContent,proportion=1,flag=wx.EXPAND,border=5)
pan.SetSizer(vbox)
# self.SetButtons('init') def BtnOpenHandler(self,event):
dlg = wx.DirDialog(None,u"选择文件夹",style=wx.DD_DEFAULT_STYLE)
if dlg.ShowModal() == wx.ID_OK:
dlg.Destroy()
if dlg.GetPath():
self.dirSelected=dlg.GetPath() #文件夹路径
self.txtFile.SetValue(self.dirSelected) self.SetButtons('selected')
self.txtContent.SetValue('Selected dirctory: %s\n'%self.dirSelected) def BtnListHandler(self,event):
if not self.txtFile.GetValue() or not os.path.isdir(self.txtFile.GetValue()):
wx.MessageBox('please select a valid directory first.','Tip Message',wx.YES_DEFAULT|wx.ICON_INFORMATION)
return
self.dirSelected=self.txtFile.GetValue()
self.txtContent.SetValue('')
msg='Listing same files in %s\n'%self.dirSelected
self.txtContent.SetValue(msg)
workThread=WorkerThread(self,self.dirSelected,'list',msg) def BtnRemoveHandler(self,event):
if not self.txtFile.GetValue() or not os.path.isdir(self.txtFile.GetValue()):
wx.MessageBox('please select a valid directory first.','Tip Message',wx.YES_DEFAULT|wx.ICON_INFORMATION)
return
self.dirSelected=self.txtFile.GetValue()
self.txtContent.SetValue('')
msg='Removing duplicated files in %s\n'%self.dirSelected
self.txtContent.SetValue(msg)
WorkerThread(self,self.dirSelected,'remove',msg) def BtnStopHandler(self,event):
pass def SetButtons(self,status):
if status=='init':
self.btnOpen.Enable()
self.btnList.Disable()
self.btnRemove.Disable()
# self.btnStop.Disable()
elif status=='operating':
self.btnOpen.Disable()
self.btnList.Disable()
self.btnRemove.Disable()
# self.btnStop.Enable()
elif status=='completed':
self.btnOpen.Enable()
self.btnList.Enable()
self.btnRemove.Enable()
# self.btnStop.Disable()
elif status=='selected':
self.btnOpen.Enable()
self.btnList.Enable()
self.btnRemove.Enable()
# self.btnStop.Disable() if __name__=="__main__":
app=wx.App()
MyFrame().Show()
app.MainLoop()

python查找并删除相同文件-UNIQ File-wxPython版本的更多相关文章

  1. python查找并删除相同文件-UNIQ File-script版本

    今天用wxPython做了一个GUI程序,实现查找指定目录内的相同文件,主要原理是计算文件的md5值(计算前先找出文件大小相同的文件,然后计算这些文件的md5值,而不是所有文件都计算,大大减少了md5 ...

  2. python查找并删除相同文件-UNIQ File-wxPython-v6

    相比第一版,新增:菜单,对话框,文件过滤器,操作结果保存,配置功能(自己写了一个读写配置文件的功能),提示语优化,模块分化更合理. 截图: 源代码: UniqFile-wxPython-v6.py: ...

  3. Linux查找并删除重复文件的命令行fdupes工具,dupeGuru图形工具

    查了几十个网页,找到这个接近满意的解决方案http://unix.stackexchange.com/questions/146197/fdupes-delete-files-aft... 不过正则里 ...

  4. Linux系统中查找、删除重复文件,释放磁盘空间。

    在Linux系操作系统中查找并删除重复文件的方法的确有很多,不过这里介绍的是一款非常简单实用的软件FSlint.FSlint是一个重复文件查找工具,可以使用它来清除不必要的重复文件,笔者经常使用它来释 ...

  5. Python小工具--删除svn文件

    有的时候我们需要删除项目下的svn相关文件,但是SVN会在所有的目录下都创建隐藏文件.svn,手工一个个目录查找然后删除显然比较麻烦.所以这里提供了一个Python小工具用于批量删除svn的相关文件: ...

  6. 利用lsof命令查找已经删除的文件来释放磁盘空间

    测试环境一台服务器/目录空间使用率达到97%,但是通过du -sh *发现实际空间没用到那么多,初步怀疑,之前删除的文件,有运行中的进程一直占用,导致空间没有释放,如图通过du -sh *发现共实际使 ...

  7. 在 Linux 中查找和删除重复文件

    原文链接:https://www.linuxprobe.com/linux-FSlint.html FSlint同时具有GUI和CLI模式.因此,对于新手来说,这是一个用户友好的工具.FSlint不仅 ...

  8. fso查找被删除的文件

    <html> <head> </head> <body> 源目录:<input id="txtOld" value=" ...

  9. python 递归删除空文件夹

    Python如何递归删除空文件夹 1.Python如何递归删除空文件夹,这个问题很常见.但大多数人的解决办法都是自己实现递归函数解决这个问题,其实根本不用那么麻烦.Python中的os.walk提供了 ...

随机推荐

  1. MVC5的AuthorizeAttribute详解

    现今大多数的网站尤其是购物网站都要求你登录后才能继续操作,当你匿名的将商品放入购物车后,不可能匿名购买这时可以转到登录界面让用户进行登录验证. 适用系统自带的过滤器 MVC5只要将属性[Authori ...

  2. Struts 中 ActionContext ctx.put()把数据放到ValueStack里之数据传输背后机制:ValueStack(值栈)

    1.     数据传输背后机制:ValueStack(值栈) 在这一切的背后,是因为有了ValueStack(值栈)! ValueStack基础:OGNL要了解ValueStack,必须先理解OGNL ...

  3. python实用笔记,加快编程速度,lamdba,三元运算,open.

    lamdba   表达式.    #   f1=lamdba x:x+1 三元运算                 #    b=True if 1 < 2 else False with op ...

  4. 柱状堆积图Echarts

    Map<String,Object> map = new HashMap<String, Object>(); //图例的千人.双百 HashMap<String, St ...

  5. Mysql 常用函数

    统计函数: count()   统计记录条数,如 select count(*) from stu; sum()     统计记录字段的和,如select sum(salary) from emp; ...

  6. php后台多用户权限组思路与实现程序代码

    网站开发少不了有网站后台,有了后台自然要对用户有同角色来分配一下,特别是多用户系统的情况下,如我一个系统要有多个管理员,那么我这些管理要分成,编辑,友情连接,管理员等,那我们要有权限和角色分配,今天我 ...

  7. Properties类的使用方法

    它提供了几个主要的方法: 1. getProperty ( String key),用指定的键在此属性列表中搜索属性.也就是通过参数 key ,得到 key 所对应的 value. 2. load ( ...

  8. 移动WebApp利用Chrome浏览器进行调试

    详细的请看这个(HBuilder是我长期使用,而且值得支持的国内前端开发编辑器) http://ask.dcloud.net.cn/article/151 http://ask.dcloud.net. ...

  9. 【Solr】 solr对拼音搜索和拼音首字母搜索的支持

    问:对于拼音和拼音首字母的支持,当你在搜商品的时候,如果想输入拼音和拼音首字母就给出商品的信息,怎么办呢? 实现方式有2种,但是他们其实是对应的.  用lucene实现 1.建索引, 多建一个索引字段 ...

  10. Linux中postfix邮件服务器的搭建

    postfix是Wietse Venema在IBM的GPL协议之下开发的MTA(邮件传输代理)软件.postfix是Wietse Venema想要为使用最广泛的sendmail提供替代品的一个尝试.在 ...