今天用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. Unity时钟定时器插件

    Unity时钟定时器插件 http://dsqiu.iteye.com/blog/2020603https://github.com/joserocha3/KillerCircles/blob/67a ...

  2. 2015 前端[JS]工程师必知必会

    2015 前端[JS]工程师必知必会 本文摘自:http://zhuanlan.zhihu.com/FrontendMagazine/20002850 ,因为好东东西暂时没看懂,所以暂时保留下来,供以 ...

  3. 注入问题0x00

    1.sqlmap遇到MySQL注入可以成功getshell,但是,遇到sqlserver注入未成功getshell. 2.xp_cmdshell 如何 getshell(1433未对外开放). 解决方 ...

  4. WebGrid Helper with Check All Checkboxes

    WebGrid Helper with Check All Checkboxes myEvernote Link Tuesday, September 13, 2011ASP.NET ASP.NET ...

  5. maven jar包库

    如果你的项目不是maven项目,比如ant,你的项目需要某些jar包的时候可以到maven 的jar包中心库下载 地址:http://search.maven.org/ http://mvnrepos ...

  6. Struts2源码浅析-ConfigurationProvider

    ConfigurationProvider接口 主要完成struts配置文件 加载 注册过程 ConfigurationProvider接口定义 public interface Configurat ...

  7. php中pdo例子

    下面是从其他博客看到的代码 <?php $dbh = new PDO('mysql:host=localhost;dbname=access_control', 'root', ''); $db ...

  8. 关于PHP位运算的简单权限设计

    写在最前面 最近想写一个简单的关于权限处理的东西,之前我也了解过用二进制数的位运算可以出色地完成这个任务.关于二进制数 的位运算,常见的就是“或.与.非”这三种简单运算了,当然,我也查看了下PHP手册 ...

  9. MySQL的Order By Rand()的效率问题

    MySQL很多时候需要获取随机数据,举个例子,要从tablename表中随机提取一条记录,大家一般的写法就是: 但是,后来我查了一下MYSQL的官方手册,里面针对RAND()的提示大概意思就是,在OR ...

  10. Java中将unix时间戳转化为正常显示时间

    在unix中时间戳是一串数字表示的,使用起来非常不方便,转化方式如下: //Convert Unix timestamp to normal date style public String Time ...