环境:
html
Python 2.6.6python
linux系统linux
用到的模块:filecmp正则表达式
filecmp提供了:单文件对比,多文件对比,目录对比bash
单文件对比:采用filecmp.cmp(f1,f2[,shallow])方法,比较文件名为f1和f2的文件的内容,相同返回True,不相同返回False,shallow默认是True,意思是只根据os.stat()方法返回的文件基本信息进行对比,好比最后访问时间、修改时间、状态改变时间等,会忽略文件内容的对比。当shallow为False时,则os.stat()与文件内容同时进行校验。网络
例子:app
>>> import filecmp >>> filecmp.cmp("/root/dir1/f1","/root/dir2/f1") True >>> filecmp.cmp("/root/dir1/f1","/root/dir2/f5") False
多文件对比:采用filecmp.cmpfiles(dir1, dir2, common[, shallow])方法,对比dir1与dir2目录给定的文件清单。该方法返回文件名的三个列表,分别为匹配、不匹配、错误。匹配为包含匹配的文件的列表,不匹配反之,错误列表包括了目录不存在文件、不具有读权限或其余缘由致使的不能比较的文件清单。运维
例子:ide
先创建一些文件:函数
代码:
>>> filecmp.cmpfiles("/root/dir1","/root/dir2",['f1','f2','f3','f4','f5']) (['f1', 'f2', 'f3', 'f4'], [], ['f5'])
目录对比:经过dircmp(a, b[, ignore[, hide]])类建立一个目录比较对象,其中a和b是参加比较的目录名。ignore表明文件名忽略的列表,并默认为['RCS', 'CVS', 'tags'];hide表明隐藏的列表,默认为[os.curdir,os.pardir]。dircmp类能够得到目录比较的详细信息,如只有在a目录中包括的文件、a与b都存在的子目录、匹配的文件等,同时支持递归。
例子:
#!/usr/bin/env python #-*—coding:utf-8-*- #2017,9,7 import filecmp a = "/root/dir1" #定义左目录 b = "/root/dir2" #定义右目录 dirobj = filecmp.dircmp(a,b,['1.py']) #目录比较,忽略1.py文件。 dirobj.report() #比较当前指定目录中的内容 dirobj.report_full_closure() #递归比较全部指定目录的内容 dirobj.report_partial_closure() #比较当前指定目录以及第一级目录中的内容 print "_"*50 print "left_list:" + str(dirobj.left_list) #左目录 print "_"*50 print "right_list:"+str(dirobj.right_list) #右目录 print "_"*50 print "commom:"+str(dirobj.common) #两边共同存在的目录 print "_"*50 print "left_only:"+str(dirobj.left_only) #只在左目录中的文件或者目录 print "_"*50 print "right_only:"+str(dirobj.right_only) #只在右目录中的文件或者目录 print "_"*50 print "common_dirs:"+str(dirobj.common_dirs)#两边目录都存在的子目录 print "_"*50 print "common_files:"+str(dirobj.common_files) #两边目录都存在的文件 print "_"*50 print "common_funny:"+str(dirobj.common_funny) #两边目录都存在的目录 print "_"*50 print "same_files:"+str(dirobj.same_files) #匹配相同的文件 print "_"*50 print "diff_files:" + str(dirobj.diff_files) #不匹配的文件 print "_"*50 print "funny_files:" + str(dirobj.diff_files) #两边目录中都存在,可是没法比较的文件
执行结果:
diff /root/dir1 /root/dir2 Only in /root/dir2 : ['f5'] Identical files : ['f1', 'f2', 'f3', 'f4'] diff /root/dir1 /root/dir2 Only in /root/dir2 : ['f5'] Identical files : ['f1', 'f2', 'f3', 'f4'] diff /root/dir1 /root/dir2 Only in /root/dir2 : ['f5'] Identical files : ['f1', 'f2', 'f3', 'f4'] __________________________________________________ left_list:['f1', 'f2', 'f3', 'f4'] __________________________________________________ right_list:['f1', 'f2', 'f3', 'f4', 'f5'] __________________________________________________ commom:['f1', 'f2', 'f3', 'f4'] __________________________________________________ left_only:[] __________________________________________________ right_only:['f5'] __________________________________________________ common_dirs:[] __________________________________________________ common_files:['f1', 'f2', 'f3', 'f4'] __________________________________________________ common_funny:[] __________________________________________________ same_files:['f1', 'f2', 'f3', 'f4'] __________________________________________________ diff_files:[] __________________________________________________ funny_files:[]
实践:效验源与备份目录差别
源代码:
#!/usr/bin/env python #coding:utf-8 #2017,9,7 import os import sys import filecmp import re import shutil holderlist=[] def compareme(dir1,dir2): dircomp = filecmp.dircmp(dir1,dir2) only_in_one = dircomp.left_only #源目录新文件或目录(只在左目录中的文件或者目录) diff_in_one = dircomp.diff_files #不匹配文件,源目录文件已经发生变化 dirpath = os.path.abspath(dir1) #获取源目录的绝对路径。 #将更新文件名或者目录追加到holderlist [holderlist.append(os.path.abspath(os.path.join(dir1,x))) for x in only_in_one] [holderlist.append(os.path.abspath(os.path.join(dir1,x))) for x in diff_in_one] if len(dircomp.common_dirs) > 0: for item in dircomp.common_dirs: return holderlist def main(): if len(sys.argv) > 2: dir1 = sys.argv[1] dir2 = sys.argv[2] else: print "usage:",sys.argv[0],"datadir backupdir" sys.exit() source_files = compareme(dir1,dir2) #对比源目录与备份目录 dir1 = os.path.abspath(dir1) if not dir2.endswith('/'): dir2 = dir2+'/' dir2 = os.path.abspath(dir2) destination_files = [] createdir_bool =False for item in source_files: #遍历返回的差别文件或者目录清单 destination_dir = re.sub(dir1,dir2,item) #将源目录差别路径清单对应替换成备份目录 destination_files.append(destination_dir) if os.path.isdir(item): #若是差别路径为目录且不存在,则在备份目录中建立 if not os.path.exists(destination_dir): os.makedirs(destination_dir) createdir_bool = True #再一次调用compareme函数标记 if createdir_bool: destination_files = [] source_files=[] source_files=compareme(dir1,dir2) for item in source_files: destination_dir = re.sub(dir1,dir2,item) destination_files.append(destination_dir) print "updata item:" print source_files #输出更新列表清单 copy_pair = zip(source_files,destination_files) #将源目录与备份目录文件拆分红元组 for item in copy_pair: if os.path.isfile(item[0]): #判断是否为文件,是则进行复制 shutil.copyfile(item[0],item[1]) if __name__=='__main__': main()
执行结果:
总结\注意\拓展:
总结:
本次学习不只学会了文件备份的效验,并且学习到了一个语法:
[holderlist.append(os.path.abspath(os.path.join(dir1,x))) for x in only_in_one] #正常写法 for x in only_in_one: holderlist.append(os.path.abspath(os.path.join(dir1,x)))
注意:
在写程序的时候必定要注意缩进,否则容易报错,我在写下面这句的时候就老报语法错误,作后让别人打一遍,我复制一下才成功:
return holderlist
拓展:
re.sub是re模块重要的组成部分,而且功能也很是强大,主要功能实现正则的替换
re.sub定义:
sub(pattern, repl, string, count=0, flags=0)
解释:
pattern:为表示正则中的模式字符串,
repl为replacement,被替换的内容,repl能够是字符串,也能够是函数。
string为正则表达式匹配的内容。
count:因为正则表达式匹配到的结果是多个,使用count来限定替换的个数(顺序为从左向右),默认值为0,替换全部的匹配到的结果。
flag是匹配模式,可使用按位或’|’表示同时生效,也能够在正则表达式字符串中指定。
例子:
>>>import re >>>re.sub(r'\w+','10',"ji 43 af,geq",2,flags=re.I) >>>'10 10 af,geq'
shutil模块:
详情参考:http://blog.csdn.net/xmnathan/article/details/36217631
参考连接1:https://book.2cto.com/201411/48243.html
参考连接2:http://blog.csdn.net/hjxzt1/article/details/73741507
参考资料1:百度知道
参考资料2:网络资源
参考资料3:《Python自动化运维技术与最佳实践》-刘天斯 著