今天用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. 在Nginx服务器中设置多个站点

    这里以配置1个站点(1个域名)为例,n 个站点可以相应增加调整, 假设:IP地址: 127.0.0.1域名1 phpmyadmin.zhengwen.cn 放在 /www/phpmyadmin.zhe ...

  2. js控制网页滚动条往下滚动

    function aa(i){ var tm = setInterval(function(){ var t = $(window).scrollTop(); , -) : Math.max((i-t ...

  3. 在64位系统上不能安装Matlab notebook的解决方案

    在64位系统上不能安装Matlab notebook的解决方案 过程分解 第一步:安装好matlab(附:Matalab R2015a界面) 第二步:在matlab中执行命令 >>note ...

  4. 菜鸟疑问之新建网站与新建web应用程序区别

    学习asp.net一定少不了这困惑:新建网站与新建web应用程序有什么区别? 新建web应用程序 新建网站 呵呵,其实从名字看一个是webApplication,一个是webSite.名字不同罢了? ...

  5. 使用EntityFramework6.1的DbCommandInterceptor拦截生成的SQL语句

    开始 EF6.1也出来不少日子了,6.1相比6.0有个很大的特点就是新增了System.Data.Entity.Infrastructure.Interception 命名空间,此命名空间下的对象可以 ...

  6. thinkphp 模板里a标签 href 带参数的 使用U函数方法

    简单的说就是模板里 分类的链接地址 实现这个样子的 <a href="/index.php/Home/Category/assortment/cateid/2.html"&g ...

  7. linux下使用yum安装mysql

    1. 安装mysql 服务器端:           yum install mysql-server             yum install mysql-devel 2. 安装mysql客户 ...

  8. linux shell中判断bash脚本输入的参数个数

    看下面的一段程序. #!/bin/bash ]; then echo "参数个数为$#个" else echo "没有参数" fi

  9. hdu4782 Beautiful Soup (模拟)

    http://acm.hdu.edu.cn/showproblem.php?pid=4782 2013成都区域赛全题PDF:http://acm.hdu.edu.cn/downloads/2013Ch ...

  10. 开始使用pycharm了

    我将python的主力开发工具从eclipse+pydev切换到pycharm社区版了. 选择pycharm 的原因:1. pycharm可以实时按照pep8的规范检查code style和namin ...