文件與目錄差別對比方法

環境:
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

先創建一些文件:函數

wKiom1mylGnxXlP4AABAULk2v-A832.png

代碼:

>>> 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()

執行結果:

wKiom1myllng5ONdAAAn_dj3n2c260.png


總結\注意\拓展:


總結:

本次學習不只學會了文件備份的效驗,並且學習到了一個語法:

 [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自動化運維技術與最佳實踐》-劉天斯 著


wKiom1myl5zgGMuPAAQF1aT1ixQ567.png

相關文章
相關標籤/搜索