python删除重复文件代码
来源:互联网 发布:网络验证系统哪个好 编辑:程序博客网 时间:2024/05/11 03:59
需求:查找一件夹中的文件,包括子目录中的文件,找出重名文件,然后比较大小,如果大小也相同,则删除。
方案:递归列出目录底下所有文件,并将同名文件合并到一起,用dict(java里是map)保存,键用文件名,而值用列表,保存文件名对应的路径。然后去除map值中len为1数项目。接着循环map,判断时间是否相同,相同则删除
下面是我的实现过程:
我打算写个递归函数,遍历目录底下的所有文件。这个函数参数除了要遍历的目录路径,还有一个函数参数,用来处理每次遍历的文件。如果是java里面,我当然会用策略模式:比如定义一个处理文件的接口,传给遍历目录的方法。java8里面的lambda表达式也使策略模式使用起来更加方便灵活。但python可以直接传方法作为参数,这样我们就不用定义接口了(事实上我更喜欢java用接口作参数。)
第一步遍历文件,并按文件名,进行分组操作,代码如下
import osimport os.path##处理文件def processFile(path, processFun): ''' 用来处理遍历文件 :param path: 要处理文件路径 :param processFun: 对某一文件处理的方法 :return: ''' fileList = os.walk(path) for dirpath, dirnames, filenames in fileList: for mFname in filenames: processFun(dirpath, mFname)rFdic = dict();def process1(dirpath, filename): if (filename not in rFdic): rFdic[filename] = [dirpath] else: rList = rFdic[filename] rList.append(dirpath)processFile("/Users/wzp/tmp/file/", process1)for k1 in [k for k in rFdic if len(rFdic[k]) ==1]: rFdic.pop(k1)print(rFdic)
processFile方法是我计划用来实逻辑的主体的方法。里面实现了对文件的遍历(我本想用递归的,但python里面有现成的方法)。此外遍历到每个文件时调用processFun方法(不好意,我没有做精心的方法命名)。这个函数是作为参数传进来的。这样可以实现我业务的分离。下面调用processFile且传递了相应的路径,将方法process1参数传了进去。process1主要实现了分组操作,代码很简单。但写完后,我发现了一个问题。那就是分组完成后,我希望对数据再进行一个处理,比如在调用processFile后,我用了一个for方法,将rFdic中的没有重复的数据去除掉。然而我并不想在方法外做,我想最后只用调用processFile便可完成所有操作。怎么办?当然是在方法上增加一个参数,这个参数也传递一个方法,这个方法在遍历文档结束后调用,用来处理分组后的数据。妈的,我突然想到,我的做法好像跟google的MapReduce相似。虽然我还没仔细研究过MapReduce,但MapReduce的思路好像也是类似。好吧,我添加一个参数,同时借用google的map和reduce方法名(虽然我原计划我processFile方法不局限于分组删除之类的,不过我一时取不出好的方法名),
版2 的代码如下:
import osimport os.pathdef processFile(path, filemap, filereduce): fileList = os.walk(path) for dirpath, dirnames, filenames in fileList: for mFname in filenames: filemap(dirpath, mFname) filereduce()rFdic = dict();def map1(dirpath, filename): # print(dirpath + filename) if (filename not in rFdic): rFdic[filename] = [dirpath] else: rList = rFdic[filename] rList.append(dirpath)def reduce1(): for k1 in [k for k in rFdic if len(rFdic[k]) == 1]: rFdic.pop(k1) for k1 in rFdic: for mdir in rFdic[k1]: mpath = mdir + "/" + k1 print(mpath + "\t|\t", os.path.getsize(mpath))def reduce2(): for k1 in [k for k in rFdic if len(rFdic[k]) == 1]: rFdic.pop(k1) for k1 in rFdic: mfsize = -1 for mdir in rFdic[k1]: mpath = mdir + "/" + k1 tfsize = os.path.getsize(mpath) if (tfsize == mfsize): print("del file"+mpath,tfsize) mfsize = tfsize;processFile("/Users/wzp/tmp/file/", map1, reduce2)print(rFdic)
我们改变了 processFile的参数名,并且增加了一个参数。你可以看到我这里用的方法跟mapreduce是不一样的,mapreduce中用map输出的参数作为reduce输入的参数。我们这里没有这个必要,因为这两个方法可以共享一个变量,当然也可以把两个方法写到一个类中,这样就不用完全局变量了。此外,我们这里有个reduce1方法,和reduce2方法。他们可以实现不同的逻辑,在调用processFile时,想要什么样的算法,可以传相应的reduce进去。你可能注意到redduce1和reduce2有两段重复的代码。其实如果是java中,可以用组合模式。
版本3:
import osimport os.pathdef processFile(path, filemap, filereduce): fileList = os.walk(path) for dirpath, dirnames, filenames in fileList: for mFname in filenames: filemap(dirpath, mFname) filereduce()rFdic = dict();def map1(dirpath, filename): # print(dirpath + filename) if (filename not in rFdic): rFdic[filename] = [dirpath] else: rList = rFdic[filename] rList.append(dirpath)def reduce0(): for k1 in [k for k in rFdic if len(rFdic[k]) == 1]: rFdic.pop(k1)def reduce1(): for k1 in rFdic: for mdir in rFdic[k1]: mpath = mdir + "/" + k1 print(mpath + "\t|\t", os.path.getsize(mpath))def reduce2(): for k1 in rFdic: mfsize = -1 for mdir in rFdic[k1]: mpath = mdir + "/" + k1 tfsize = os.path.getsize(mpath) if (tfsize == mfsize): os.remove(mpath) print("deleted file :"+mpath) mfsize = tfsize;def reduce3(): reduce0() print("do you want delete these files?") reduce1() str = input("Enter Y or N ") if str != "Y": print("file not delete ") return print("start delte file") reduce2()processFile("/Users/wzp/Downloads/xx", map1, reduce3)
我们没有改变我们processFile方法,只是添加两个reduce方法,在方法reduce3里面,我们调用了其它几个reduce方法。ok完成。尽管功能已完成,但还是不如人意,于是我想到了版本5(你或许会问,版本4呢?4没贴出来,我想直接跳5)。首先我们是文件名与文件大小来判断是否是同一文件。于是我们在map方法中,就能按文件名与文件大小联合在一起分组。
def fileNameAndSizeMap(dirpath, filename): mFilePath = dirpath + "/" + filename mkey = mFilePath + "|" + str(os.path.getsize(mFilePath)); if (mkey not in rFdic): rFdic[mkey] = [dirpath] else: rList = rFdic[mkey] rList.append(filename) processFile("/Users/wzp/Downloads/xx", fileNameAndSizeMap, lambda:print(rFdic))
其他方法不用改变,我们只需要添加两个方法即可,以上我添加map方法,用文件名与文件大小作为键,值改成了文件全路径,这样可以省去很多麻烦,但我没我写reduce了,引用lambda表达式,直接将rFdic中的值直接打印出来,以后再完善。困了,半睡眠状态写的
- python删除重复文件代码
- 删除重复文件的脚本代码
- 【Python】删除重复文件 并重命名
- python删除xml文件中重复词条
- python文件去除重复的代码示例
- Python代码实现:删除一个list里面的重复元素
- 如何用Python寻找重复文件并删除
- 使用python删除本地夹里重复的文件
- 删除重复文件sql
- java 删除重复文件
- shell 删除重复文件
- 删除重复文件
- sql 删除重复列代码
- python--删除队列重复元素
- python 删除/查找重复项
- python查找/删除重复记录
- python 文件去重复
- 删除重复的脚本文件
- 前置配置
- tensorflow 的MNIST实现
- VMware中三种网络模式设置指南
- nagios安装后提示 statusmap.cgi找不到的解决办法
- HDU 1532 Drainage Ditches(最大流+EK算法模板题)
- python删除重复文件代码
- 【python】采集免费代理ip并验证可用性后存储到文件
- slidingmenu左右侧滑页面
- 火狐浏览器安全插件
- js实现复制到剪切板
- HDU-5512-Pagodas
- bzoj4953 [Wf2017]Posterize(区间dp)
- bzoj 1629: [Usaco2007 Demo]Cow Acrobats(贪心排序)
- GoTo 递归