Python 之 filecmp

2017年7月12日

参考书籍:《Python自动化运维 ——技术与最佳实践》 作者:李天斯

1.什么是filecmp

filecmp作为python的标准库,无需安装,作用是对文件,目录,遍历子目录的差异对比功能,它是一个轻量级的工具,在对linux服务器备份文件检验时非常有用。

2.filecmp的简单使用

2.1 cmp的简单使用

用法:filecmp.cmp(file1,file2),如果file1和file2相同的话,则会返回true,否则返回false,这就称为比较单文件的差异。

2.1.1 copy一个文件备份两次

 # cp /etc/vnc.conf ./
 # cp /etc/vnc.conf ./vnc.conf.bak

2.1.2 编写python代码

 # cat lcmp.py

 #!/usr/bin/env python

 import sys

 import filecmp

 import os

 try:

     file1 = sys.argv[1]

     file2 = sys.argv[2]

 except:

     print ("Please follow the parameters")

     sys.exit()

 if os.path.isfile(file1) and os.path.isfile(file2) :

     if filecmp.cmp(file1,file2):

         print ("Match success")

     else :

         print ("Match failed")

 else:

     print ("Please check files")

     sys.exit()

2.1.2 执行脚本输出

 # python lcmp.py vnc.conf vnc.conf.bak
 Match success

由上诉结果可以看出,文件是对比OK了的,现在修改vnc.conf.bak的内容,再执行脚本

2.1.3再次执行

 # sed -i s/vnc/liwang.org/ vnc.conf.bak
 # python lcmp.py vnc.conf vnc.conf.bak
 Match failed

比对文件不成功,则输出了Match failed ,则证明脚本是ok的

2.2 cmpfiles的简单使用

用法:filecmp.cmpfiles(dir1,dir2,common[files...]),作用是对比dir1 和 dir2 目录的差异,该方法会返回三个list,分别是匹配,不匹配,错误。

2.2.1 复制文件

 # mkdir -p dir1 dir2
 # cp lcmp.py vnc.conf vnc.conf.bak dir1/
 # cp lcmp.py vnc.conf dir2/

2.2.2 编写python代码

 # cat lcmpfiles.py

 #!/usr/bin/env python

 import os

 import filecmp

 import sys

 dir1 = input("Please enter a folder to match:")

 dir2 = input("Please enter a folder to match:")

 files = []

 while True:

     local_files = input("Please enter the file to compare:[n/N Exit the input]")

     if local_files == 'N' or local_files == 'n':

         break

     elif local_files == '':

         continue

     else :

         files.append(local_files)

 try:

     os.path.exists(dir1)

     os.path.exists(dir2)

 except:

     print ("Pleae check the folder.")

     sys.exit()

 #print (filecmp.cmpfiles(dir1,dir2,files)[0])

 print ("It's file match:",filecmp.cmpfiles(dir1,dir2,files)[0])

 print ("The file does not match:",filecmp.cmpfiles(dir1,dir2,files)[1])

 print ("File does not exists:",filecmp.cmpfiles(dir1,dir2,files)[2])

2.2.3 用python3执行脚本(因为使用了input)

 # python3 lcmpfiles.py
 Please enter a folder to match:dir1
 Please enter a folder to match:dir2
 Please enter the file to compare:[n/N Exit the input]lcmp.py
 Please enter the file to compare:[n/N Exit the input]vnc.conf
 Please enter the file to compare:[n/N Exit the input]vnc.conf.bak
 Please enter the file to compare:[n/N Exit the input]n
 It's file match: ['lcmp.py', 'vnc.conf']
 The file does not match: []
 File does not exists: ['vnc.conf.bak']

可以看出,lcmp.py 和 vnc.conf 在dir1 和dr2都有,且文件内容相同,而vnc.conf.bak在dir1有,dir没有,故输出,文件匹配:lcmp.py和vnc.conf ,文件不存在:vnc.conf.bak,文件不相同:无

2.2 dircmp的简单使用

语法:dircmp(a,b,[,ignore[,hide]]) 其中a,b是文件名,ignore是可以忽略的列表,hide代表隐藏列表,dircmp可以获得目录比较详细的信息,同时还支持递归。

dircmp提供了三个输出方法:

report() 比较当前指定目录中的内容

report_full_closure() 递归比较所有指定文件的内容

2.2.1 模拟环境

 # ls dir1/ dir2/
 dir1/:
 hosts  ld.so.conf  sysconfig

 dir2/:
 hosts  ld.so.conf  sysconfig

其中,sysconfig 是一个目录 hosts 和 ld.so.conf都是文件,且hosts内容不一致 sysconfig中的文件也不一样

2.2.2 编写python代码

2.2.2.1 dircmp.report()

 # cat simple_filecmp.py

 #!/usr/bin/env python

 import filecmp

 dir1 = "/root/python/d_2_filecmp/cmp/dir2"

 dir2 = "/root/python/d_2_filecmp/cmp/dir1"

 dirobj = filecmp.dircmp(dir1,dir2)

 print (dirobj.report()) 

2.2.2.2 执行脚本

 # python simple_filecmp.py
 diff /root/python/d_2_filecmp/cmp/dir2 /root/python/d_2_filecmp/cmp/dir1
 Identical files : ['ld.so.conf']
 Differing files : ['hosts']
 Common subdirectories : ['sysconfig']
 None
 [root@localhost cmp]# cat simple_filecmp.py 

由上面的结果,我们可以看出,report只能比对脚本的首层目录,而无法对子文件夹下的目录进行匹配

2.2.2.3 report_full_closure()

 # cat simple_filecmp_2.py

 #!/usr/bin/env python

 import filecmp

 dir1 = "/root/python/d_2_filecmp/cmp/dir1/"

 dir2 = "/root/python/d_2_filecmp/cmp/dir2/"

 dirobj = filecmp.dircmp(dir1,dir2)

 print (dirobj.report_full_closure())

2.2.2.4 执行脚本

 diff /root/python/d_2_filecmp/cmp/dir1/ /root/python/d_2_filecmp/cmp/dir2/
 Identical files : ['ld.so.conf']
 Differing files : ['hosts']
 Common subdirectories : ['sysconfig']

 diff/root/python/d_2_filecmp/cmp/dir1/sysconfig /root/python/d_2_filecmp/cmp/dir2/sysconfig
 ......

由此可见差别report()和report_full_closure()的差别在于

3.filecmp案例

3.1 需求

需求:1.备份etc 文件夹下所有的内容,并且保持实时备份,如果有新的文件,则copy至备份文件中,如果有新的,则update之

3.2 流程图

3.2.1 初步流程图:

3.2.2 对比文件差异流程图

3.3 代码编写:

3.3.1 补充知识:

dircmp.left_only

只在左边出现的文件

 # cat simple_filecmp_3.py

 #!/usr/bin/env python

 import filecmp

 dir1 = "/root/python/d_2_filecmp/cmp/dir1/"

 dir2 = "/root/python/d_2_filecmp/cmp/dir2/"

 dirobj = filecmp.dircmp(dir1,dir2)

 print (dirobj.diff_files)

执行结果

 # ls dir1 dir2/
 dir1:
 hosts  ld.so.conf  sysconfig  teacher

 dir2/:
 hosts  ld.so.conf  sysconfig
 [root@localhost cmp]# python simple_filecmp_3.py
 ['teacher']

由上诉可见,当teacher只出现在dir1时,则会被抓取出来,所谓的left和right是相对于filecmp.dircmp而言的

dircmp.diff_files

返回不能匹配额文件

 # cat simple_filecmp_3.py

 #!/usr/bin/env python

 import filecmp

 dir1 = "/root/python/d_2_filecmp/cmp/dir1/"

 dir2 = "/root/python/d_2_filecmp/cmp/dir2/"

 dirobj = filecmp.dircmp(dir1,dir2)

 print (dirobj.diff_files)

 #print (dirobj.left_only)

执行结果

 [root@localhost cmp]# ls dir1 dir2
 dir1:
 hosts  ld.so.conf  sysconfig  teacher

 dir2:
 hosts  ld.so.conf  sysconfig
 [root@localhost cmp]# python simple_filecmp_3.py
 ['hosts']
 [root@localhost cmp]# 

之前我们修改过hosts的文件,文件内容已经不一致,现在已经被抓取出来了

3.3.2 编写自动备份脚本

 # cat d_7_12_filecmp.py
 #!/usr/bin/env python

 import filecmp
 import os
 import sys
 import shutil

 source_files = "/root/python/d_2_filecmp/dir1"
 target_files = "/root/python/d_2_filecmp/dir2"

 def check_common_dirs(source_files,target_files):
     dirsobj = filecmp.dircmp(source_files , target_files)

     common_dirs_list = dirsobj.common_dirs

     for common_line in common_dirs_list :
         files_contrast('/'+source_files+'/'+common_line,'/'+target_files+'/'+common_line)

 def files_contrast(dir1,dir2) :

     dirobj = filecmp.dircmp(dir1,dir2)

     no_exists_files = dirobj.left_only
     no_diff_files = dirobj.diff_files

     for exists_files in no_exists_files :

         if os.path.isfile(exists_files) :
             shutil.copyfile ('/'+dir1+'/'+exists_files , '/'+dir2+'/'+exists_files)
         else :
             print ("%s is dirctory" %(exists_files))
             os.makedirs('/'+dir2+'/'+exists_files)
             print ("%s is mkdirs" %('/'+target_files+'/'+exists_files))

             try :
                 print ("values : %s %s" %('/'+dir1+'/'+exists_files , '/'+dir2+'/'+exists_files))
                 files_contrast('/'+dir1+'/'+exists_files , '/'+dir2+'/'+exists_files)
             except :
                 return 

     for diff_files in no_diff_files :
         if os.path.isfile(diff_files) :
             os.remove('/'+dir2+'/'+diff_files)
             shutil.copyfile ('/'+dir1+'/'+diff_files , '/'+dir2+'/'+diff_files)

 if os.path.exists(source_files) :

     if os.path.exists(target_files) == "False" :
         os.makedirs(target_files)

     files_contrast(source_files,target_files)
     check_common_dirs(source_files,target_files)

 else :
     print ("Soure files no exists")
     sys.exit()

3.4 执行脚本输出

3.4.1 查看文件

可知 dir2下没有任何文件

 # tree dir1/ dir2/
 dir1/
 ├──
 │   └──
 ├──
 │   └──
 │       └── d
 ├── lcmp.py
 ├── vnc.conf
 └── vnc.conf.bak
 dir2/

  directories,  files 

3.4.2 执行脚本

 root@localhost d_2_filecmp]# python d_7_12_filecmp.py
  is dirctory
 //root/python/d_2_filecmp/dir2/4556 is mkdirs
 values : //root/python/d_2_filecmp/dir1/4556 //root/python/d_2_filecmp/dir2/4556
  is dirctory
 //root/python/d_2_filecmp/dir2/789 is mkdirs
 values : ///root/python/d_2_filecmp/dir1/4556/789 ///root/python/d_2_filecmp/dir2/4556/789
 d is dirctory
 //root/python/d_2_filecmp/dir2/d is mkdirs
 values : ////root/python/d_2_filecmp/dir1/4556/789/d ////root/python/d_2_filecmp/dir2/4556/789/d
  is dirctory
 //root/python/d_2_filecmp/dir2/123 is mkdirs
 values : //root/python/d_2_filecmp/dir1/123 //root/python/d_2_filecmp/dir2/123
  is dirctory
 //root/python/d_2_filecmp/dir2/123456 is mkdirs
 values : ///root/python/d_2_filecmp/dir1/123/123456 ///root/python/d_2_filecmp/dir2/123/123456

可以看出,备份的信息,前面的多个/可以不必理会,linux只识别一个/

3.4.3 查看备份效果

 # tree dir1/ dir2/
 dir1/
 ├──
 │   └──
 ├──
 │   └──
 │       └── d
 ├── lcmp.py
 ├── vnc.conf
 └── vnc.conf.bak
 dir2/
 ├──
 │   └──
 ├──
 │   └──
 │       └── d
 ├── lcmp.py
 ├── vnc.conf
 └── vnc.conf.bak

  directories,  files

由上,可知,备份完全成功,针对于定时执行python脚本,可以将脚本写入crontab中,开启定时任务即可。

Python 之 filecmp的更多相关文章

  1. IPython,让Python显得友好十倍的外套——windows XP/Win7安装详解

        前言 学习python,官方版本其实足够了.但是如果追求更好的开发体验,耐得住不厌其烦地折腾.那么我可以负责任的告诉你:IPython是我认为的唯一显著好于原版python的工具.   整理了 ...

  2. python简单实现目录对比

    [root@localhost python]# cat dircmptest.py #!/usr/bin/python import filecmp path1="/root/python ...

  3. python filecmp标准库基础学习

    # -*- coding: utf-8 -*-# 作者:新手__author__ = 'Administrator'#文件的比较import os,filecmp#作用用于比较系统中的目录和文件#例子 ...

  4. 【Python】 文件目录比较工具filecmp和difflib

    在一些运维场景中,常常需要比较两个环境中的应用目录结构(是否有文件/目录层面上的增删)以及比较两个环境中同名文件内容的不同(即文件层面上的改).Python自带了两个内建模块可以很好地完成这个工作,f ...

  5. python之模块filecmp(文件/目录比较)

    # -*- coding: utf-8 -*- #python 27 #xiaodeng #python之模块filecmp(文件/目录比较) #用于比较文件及文件夹的内容.他是轻量级的工具.可以做一 ...

  6. python运维开发常用模块(5)文件目录对比模块filecmp

    1.filecmp模块介绍 当我们进行代码审计或校验备份结果时,往往需要检查原始与目 标目录的文件一致性,Python的标准库已经自带了满足此需求的模块 filecmp.filecmp可以实现文件.目 ...

  7. Python模块学习filecmp文件比较

    Python模块学习filecmp文件比较 filecmp模块用于比较文件及文件夹的内容,它是一个轻量级的工具,使用非常简单.python标准库还提供了difflib模块用于比较文件的内容.关于dif ...

  8. python模块详解 | filecmp

    简介: filecmp是python内置的一个模块,用于比较文件及文件夹的内容,它是一个轻量级的工具,使用非常简单 两个主要的方法: filecmp.cmp(f1, f2[, shallow]) 比较 ...

  9. 《Python标准库》 目录

    目录 译者序序前言第1章 文本1.1 string—文本常量和模板1.1.1 函数1.1.2 模板1.1.3 高级模板1.2 textwrap—格式化文本段落1.2.1 示例数据1.2.2 填充段落1 ...

随机推荐

  1. js关于去重的写法

    break和continue的区别和作用 break和continue都是用来控制循环结构的,主要是停止循环. 1.break 有时候我们想在某种条件出现的时候终止循环而不是等到循环条件为false才 ...

  2. 【RabbitMQ】——5种队列(转)

    原文地址:https://blog.csdn.net/u012654963/article/details/76417613 应用RabbitMQ,我们可以根据需求选择5种队列之一. 一.简单队列 P ...

  3. IIS 7.5 上传文件大小限制

    上传插件:uploadify IIS版本:7.5 描述: 从IIS6升级到IIS7.5以后,网站上传文件大小被限制了,在Chrome下提示:ERR_CONNECTION_RESET,网上的各种方法都试 ...

  4. 转载:MongoDB之旅(超赞,适合初学者)

    MongoDB是目前工作中经常使用到的NoSQL数据库. 本博客只记录相关理论知识和技巧,涉及到实践的部分都会单开Blog来记录实践过程. ------------------------------ ...

  5. Vue filter-v-for 使用

    var app5 = new Vue({ el: '#app5', data: { shoppingList: [ "Milk", "Donuts", &quo ...

  6. mysql SQL 逻辑查询语句和执行顺序

    关键字的执行优先级(重点) fromwheregroup byhavingselectdistinctorder bylimit 先创建两个表 CREATE TABLE table1 ( custom ...

  7. 2D情况下,复数的意义代表旋转

    4 x i x i = - 4 就是"4"在数轴上旋转了180度. 那么4 x i = 4i 就旋转了90度. 复数的意义就表示旋转 乘以-1,表示x正半轴的数,围绕原点,逆时针偏 ...

  8. (O)js核心:作用域链

    作用域 在一个函数被调用的时候,函数的作用域才会存在.此时,在函数还没有开始执行的时候,开始创建函数的作用域:   函数作用域的创建步骤: 1.函数形参的声明. 2.函数变量的声明. 3.普通变量的声 ...

  9. python: "TypeError: 'type' object is not subscriptable"

    目前stackoverflow找到两种情况的解决办法: 1.TypeError: 'type' object is not subscriptable when indexing in to a di ...

  10. CF Round #509 (Div. 2)

    前言:第一次打\(CF\),因为经验不足以及英语水平很烂,即便在机房大佬的带领下也是花了好久才读懂题目..\(A\)题直到\(11\)分钟才\(A\),题目一共才做了\(4\)题,太菜了.. A. H ...