python查找并删除相同文件-UNIQ File-wxPython版本
今天用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版本的更多相关文章
- python查找并删除相同文件-UNIQ File-script版本
今天用wxPython做了一个GUI程序,实现查找指定目录内的相同文件,主要原理是计算文件的md5值(计算前先找出文件大小相同的文件,然后计算这些文件的md5值,而不是所有文件都计算,大大减少了md5 ...
- python查找并删除相同文件-UNIQ File-wxPython-v6
相比第一版,新增:菜单,对话框,文件过滤器,操作结果保存,配置功能(自己写了一个读写配置文件的功能),提示语优化,模块分化更合理. 截图: 源代码: UniqFile-wxPython-v6.py: ...
- Linux查找并删除重复文件的命令行fdupes工具,dupeGuru图形工具
查了几十个网页,找到这个接近满意的解决方案http://unix.stackexchange.com/questions/146197/fdupes-delete-files-aft... 不过正则里 ...
- Linux系统中查找、删除重复文件,释放磁盘空间。
在Linux系操作系统中查找并删除重复文件的方法的确有很多,不过这里介绍的是一款非常简单实用的软件FSlint.FSlint是一个重复文件查找工具,可以使用它来清除不必要的重复文件,笔者经常使用它来释 ...
- Python小工具--删除svn文件
有的时候我们需要删除项目下的svn相关文件,但是SVN会在所有的目录下都创建隐藏文件.svn,手工一个个目录查找然后删除显然比较麻烦.所以这里提供了一个Python小工具用于批量删除svn的相关文件: ...
- 利用lsof命令查找已经删除的文件来释放磁盘空间
测试环境一台服务器/目录空间使用率达到97%,但是通过du -sh *发现实际空间没用到那么多,初步怀疑,之前删除的文件,有运行中的进程一直占用,导致空间没有释放,如图通过du -sh *发现共实际使 ...
- 在 Linux 中查找和删除重复文件
原文链接:https://www.linuxprobe.com/linux-FSlint.html FSlint同时具有GUI和CLI模式.因此,对于新手来说,这是一个用户友好的工具.FSlint不仅 ...
- fso查找被删除的文件
<html> <head> </head> <body> 源目录:<input id="txtOld" value=" ...
- python 递归删除空文件夹
Python如何递归删除空文件夹 1.Python如何递归删除空文件夹,这个问题很常见.但大多数人的解决办法都是自己实现递归函数解决这个问题,其实根本不用那么麻烦.Python中的os.walk提供了 ...
随机推荐
- Unity时钟定时器插件
Unity时钟定时器插件 http://dsqiu.iteye.com/blog/2020603https://github.com/joserocha3/KillerCircles/blob/67a ...
- 2015 前端[JS]工程师必知必会
2015 前端[JS]工程师必知必会 本文摘自:http://zhuanlan.zhihu.com/FrontendMagazine/20002850 ,因为好东东西暂时没看懂,所以暂时保留下来,供以 ...
- 注入问题0x00
1.sqlmap遇到MySQL注入可以成功getshell,但是,遇到sqlserver注入未成功getshell. 2.xp_cmdshell 如何 getshell(1433未对外开放). 解决方 ...
- WebGrid Helper with Check All Checkboxes
WebGrid Helper with Check All Checkboxes myEvernote Link Tuesday, September 13, 2011ASP.NET ASP.NET ...
- maven jar包库
如果你的项目不是maven项目,比如ant,你的项目需要某些jar包的时候可以到maven 的jar包中心库下载 地址:http://search.maven.org/ http://mvnrepos ...
- Struts2源码浅析-ConfigurationProvider
ConfigurationProvider接口 主要完成struts配置文件 加载 注册过程 ConfigurationProvider接口定义 public interface Configurat ...
- php中pdo例子
下面是从其他博客看到的代码 <?php $dbh = new PDO('mysql:host=localhost;dbname=access_control', 'root', ''); $db ...
- 关于PHP位运算的简单权限设计
写在最前面 最近想写一个简单的关于权限处理的东西,之前我也了解过用二进制数的位运算可以出色地完成这个任务.关于二进制数 的位运算,常见的就是“或.与.非”这三种简单运算了,当然,我也查看了下PHP手册 ...
- MySQL的Order By Rand()的效率问题
MySQL很多时候需要获取随机数据,举个例子,要从tablename表中随机提取一条记录,大家一般的写法就是: 但是,后来我查了一下MYSQL的官方手册,里面针对RAND()的提示大概意思就是,在OR ...
- Java中将unix时间戳转化为正常显示时间
在unix中时间戳是一串数字表示的,使用起来非常不方便,转化方式如下: //Convert Unix timestamp to normal date style public String Time ...