文件内容差异比对--difflib、filecmp

   difflib作为python的标准库模块,无需安装,作用是对比文本之间的差异,且支持输出可读性比较强的HTML文档,与Linux下的diff命令类似。我们可以使用difflib对比代码、配置文件的差别,在版本控制方面是非常有用。

1、两个字符串的差异对比

 1 #!/usr/bin/env python
 2 #coding=utf-8
 3 import difflib
 4 
 5 #比对两个字符串中的不同点
 6 text1 = "text1 hello world!"   #定义字符串
 7 text1_lines = text1.splitlines()  #进行分隔,以便进行对比
 8 text2 = "text2 Hello World."
 9 text2_lines = text2.splitlines()
10 
11 a = difflib.Differ()  #创建Differ()对象
12 diff = a.compare(text1_lines,text2_lines)  #采用compare方法对字符串进行比较
13 print '\n'.join(list(diff)) 

 

实践对比Nginx配置文件差异

 1 #!/usr/bin/env python
 2 #coding=utf-8
 3 
 4 import difflib
 5 import sys
 6 try:
 7     textfile1 = sys.argv[1]  #第一个配置文件路径参数
 8     textfile2 = sys.argv[2]  #第二个配置文件路径参数
 9 
10 except Exception,e:     
11     print "Error:" + str(e)
12     print "Usage: file_diff.py filename1 filename2"
13     sys.exit()
14 
15 def readfile(filename):    #文件读取分隔函数
16     try:
17         fileHandle = open (filename, 'rb')
18         text = fileHandle.read().splitlines()  #读取以后进行分隔
19         fileHandle.close()
20         return text
21     except IOError as error:
22         print ('Read file Error:' + str(error))
23         sys.exit()
24 
25 if textfile1 == "" or textfile2 == "":
26     print "Usage: file_diff.py filename1 filename2"
27     sys.exit()
28 
29 text1_lines = readfile(textfile1)  #调用readfile函数,获取分隔后的字符串
30 text2_lines = readfile(textfile2)
31 
32 d = difflib.HtmlDiff()   #创建HtmlDiff()类对象
33 print d.make_file(text1_lines,text2_lines)  #通过make_file方法输出HTML格式的对比结果
34 
35 运行如下代码:
36 python sample.py nginx.conf.v1 nginx.conf.v2 > diff.html

 

2、文件与目录差异对比方法

filecmp提供了三个操作方法,分别是cmp(单文件对比)、cmpfiles(多文件对比)、dircmp(目录对比)

 1 #!/usr/bin/env python
 2 # -*- coding: utf-8 -*-
 3 
 4 import os, sys
 5 import filecmp
 6 import re
 7 import shutil
 8 
 9 holderlist = []
10 
11 ##对应第一个步骤
12 def compare_me(dir1, dir2):   #递归获取更新项函数
13     dircomp = filecmp.dircmp(dir1, dir2)
14     only_in_one = dircomp.left_only   #源目录新文件或目录
15     diff_in_one = dircomp.diff_files  #不匹配文件,源目录已发生变化
16     dirpath = os.path.abspath(dir1)   #定义源目录绝对路径
17 
18     #将更新文件名或者目录追加到holderlist
19     [ holderlist.append(os.path.abspath(os.path.join(dir1, x))) for x in only_in_one ]
20     [ holderlist.append(os.path.abspath(os.path.join(dir1, x))) for x in diff_in_one ]
21     if len(dircomp.common_dirs) > 0:
22         for item in dircomp.common_dirs:
23             compare_me(os.path.abspath(os.path.join(dir1, item)), os.path.abspath(os.path.join(dir2, item)))
24     return holderlist
25 
26 ##对应第二个步骤
27 def main():
28     if len(sys.argv) > 2:   #要求输入源目录与备份目录
29         dir1 = sys.argv[1]
30         dir2 = sys.argv[2]
31     else:
32         print "Usage: ", sys.argv[0], "datadir backupdir"
33         sys.exit()
34 
35     source_files = compare_me(dir1, dir2)  #对比源目录与备份目录
36     dir1 = os.path.abspath(dir1)
37     if not dir2.endswith('/'):  #备份目录路径加"/"符
38         dir2 = dir2 + '/'
39     dir2 = os.path.abspath(dir2)
40     destination_files = []
41     createdir_bool = False
42 
43     for item in source_files:   #遍历返回的差异文件或目录清单
44         destination_dir = re.sub(dir1, dir2, item)   #将源目录差异路径清单对应替换成备份目录
45         destination_files.append(destination_dir)
46         if os.path.isdir(item):  #如果差异路径为目录且不存在,则备份目录中创建
47             if not os.path.exists(destination_dir):
48                 os.makedirs(destination_dir)
49                 createdir_bool = True  #再次调用compareme函数标记
50 
51      ##对应第三个步骤    
52     if createdir_bool:   #重新调用compareme函数,重新遍历新创建目录的内容
53         destination_files = []
54         source_files = []
55         source_files = compare_me(dir1, dir2)   #调用compareme函数
56         for item in source_files:   #获取源目录差异路径清单,对应替换成备份目录
57             destination_dir = re.sub(dir1, dir2, item)
58             destination_files.append(destination_dir)
59 
60     ##对应第四个步骤
61     print "update item: "
62     print source_files  #输出更新项列表清单
63     copy_pair = zip(source_files, destination_files)  #将源目录与备份目录文件清单拆分成元祖
64     print "copy_pair is %s" % copy_pair
65     for item in copy_pair:
66         print "item is %s,  %s" % (item[0], item[1])
67         if os.path.isfile(item[0]):   #判断是否为文件,是则进行复制操作
68             shutil.copyfile(item[0], item[1])
69 
70 if __name__ == '__main__':
71     main()

 

posted @ 2018-01-07 14:08  飞奔的小水牛  阅读(1387)  评论(0编辑  收藏  举报