文件与目录差异对比方法

简介:

环境:

Python 2.6.6

linux系统


用到的模块:filecmp

filecmp提供了:单文件对比,多文件对比,目录对比


单文件对比:采用filecmp.cmp(f1,f2[,shallow])方法,比较文件名为f1和f2的文件的内容,相同返回True,不相同返回False,shallow默认是True,意思是只根据os.stat()方法返回的文件基本信息进行对比,比如最后访问时间、修改时间、状态改变时间等,会忽略文件内容的对比。当shallow为False时,则os.stat()与文件内容同时进行校验。


例子:

1
2
3
4
5
>>>  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目录给定的文件清单。该方法返回文件名的三个列表,分别为匹配、不匹配、错误。匹配为包含匹配的文件的列表,不匹配反之,错误列表包括了目录不存在文件、不具备读权限或其他原因导致的不能比较的文件清单。

例子:

先建立一些文件:

wKiom1mylGnxXlP4AABAULk2v-A832.png

代码:

1
2
>>> 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都存在的子目录、匹配的文件等,同时支持递归。


例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#!/usr/bin/env python
#-*—coding:utf-8-*-
#2017,9,7
 
import  filecmp
 
=  "/root/dir1"  #定义左目录
=  "/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)  #两边目录中都存在,但是无法比较的文件

执行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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:[]


实践:效验源与备份目录差异

源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#!/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  in  only_in_one]
         [holderlist.append(os.path.abspath(os.path.join(dir1,x)))  for  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()

执行结果:

wKiom1myllng5ONdAAAn_dj3n2c260.png


总结\注意\拓展:


总结:

本次学习不仅学会了文件备份的效验,而且学习到了一个语法:

1
2
3
4
  [holderlist.append(os.path.abspath(os.path.join(dir1,x)))  for  in  only_in_one]
  #正常写法
  for  in  only_in_one:
      holderlist.append(os.path.abspath(os.path.join(dir1,x)))

注意:

在写程序的时候一定要注意缩进,不然容易报错,我在写下面这句的时候就老报语法错误,做后让别人打一遍,我复制一下才成功:

1
return  holderlist


拓展:

re.sub是re模块重要的组成部分,并且功能也非常强大,主要功能实现正则的替换

re.sub定义: 
sub(pattern, repl, string, count=0, flags=0)


解释:

pattern:为表示正则中的模式字符串, 
repl为replacement,被替换的内容,repl可以是字符串,也可以是函数。 
string为正则表达式匹配的内容。 
count:由于正则表达式匹配到的结果是多个,使用count来限定替换的个数(顺序为从左向右),默认值为0,替换所有的匹配到的结果。 
flag是匹配模式,可以使用按位或’|’表示同时生效,也可以在正则表达式字符串中指定。

例子:

1
2
3
>>> 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自动化运维技术与最佳实践》-刘天斯 著


wKiom1myl5zgGMuPAAQF1aT1ixQ567.png



本文转自 天道酬勤VIP 51CTO博客,原文链接:http://blog.51cto.com/tdcqvip/1963827


相关文章
linux实用技巧:cp时自动将软链接所指定的文件实体也一起copy(软链接将会变成目标文件实体)
linux实用技巧:cp时自动将软链接所指定的文件实体也一起copy(软链接将会变成目标文件实体)
linux实用技巧:cp时自动将软链接所指定的文件实体也一起copy(软链接将会变成目标文件实体)
|
4月前
|
定位技术 Python
Python依据某一文件夹中大量文件的名称复制另一文件夹中的同名文件
Python依据某一文件夹中大量文件的名称复制另一文件夹中的同名文件
|
7月前
|
XML 存储 数据格式
基于大量文件的名称特征自动新建多个文件夹并自动复制对应文件:Python
本文介绍基于Python,对一个文件夹下大量栅格影像,基于其各自文件名,分别创建指定名称的新文件夹,并将对应影像文件复制到不同的新文件夹下的方法。
112 3
基于大量文件的名称特征自动新建多个文件夹并自动复制对应文件:Python
C#编程学习13:文件及文件夹检索与拷贝
C#编程学习13:文件及文件夹检索与拷贝
python相对路径文件无法读取,更改工作路径
python相对路径文件无法读取,更改工作路径
python相对路径文件无法读取,更改工作路径
成功解决WIN系统如何更改默认放在C盘的【我的文档】/【图片】位置的存储路径(修改到其它非系统的盘符)
成功解决WIN系统如何更改默认放在C盘的【我的文档】/【图片】位置的存储路径(修改到其它非系统的盘符)
成功解决WIN系统如何更改默认放在C盘的【我的文档】/【图片】位置的存储路径(修改到其它非系统的盘符)
|
Linux
如何在 Linux 上一次性批量重命名一组文件?
在 Linux 中,我们对文件进行重命名一般都会使用到 mv 命令,这在对单个文件重命名时非常方便。但是,若我们想要对一组文件进行重命名,mv 就有些乏力了。不过没关系,今天我们来介绍一个好用的可以实现批量重命名的命令—— rename 命令。
215 0
|
Shell Linux
Linux 技术篇-文件大小查看方法实例演示,查看指定文件大小,查看列表下所有文件夹和文件的大小
Linux 技术篇-文件大小查看方法实例演示,查看指定文件大小,查看列表下所有文件夹和文件的大小
161 0
Linux 技术篇-文件大小查看方法实例演示,查看指定文件大小,查看列表下所有文件夹和文件的大小