Python 之 filecmp 2017年7月12日 參考書籍:《Python自動化運維 ——技術與最佳實踐》 作者:李天斯 1.什麼是filecmp filecmp作為python的標準庫,無需安裝,作用是對文件,目錄,遍歷子目錄的差異對比功能,它是一個輕量級的工具,在對linux伺服器備份文件 ...
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一個文件備份兩次
1 # cp /etc/vnc.conf ./ 2 # cp /etc/vnc.conf ./vnc.conf.bak
2.1.2 編寫python代碼
1 # cat lcmp.py 2 3 #!/usr/bin/env python 4 5 import sys 6 7 import filecmp 8 9 import os 10 11 try: 12 13 file1 = sys.argv[1] 14 15 file2 = sys.argv[2] 16 17 except: 18 19 print ("Please follow the parameters") 20 21 sys.exit() 22 23 if os.path.isfile(file1) and os.path.isfile(file2) : 24 25 if filecmp.cmp(file1,file2): 26 27 print ("Match success") 28 29 else : 30 31 print ("Match failed") 32 33 else: 34 35 print ("Please check files") 36 37 sys.exit()
2.1.2 執行腳本輸出
1 # python lcmp.py vnc.conf vnc.conf.bak 2 Match success
由上訴結果可以看出,文件是對比OK了的,現在修改vnc.conf.bak的內容,再執行腳本
2.1.3再次執行
1 # sed -i s/vnc/liwang.org/ vnc.conf.bak 2 # python lcmp.py vnc.conf vnc.conf.bak 3 Match failed
比對文件不成功,則輸出了Match failed ,則證明腳本是ok的
2.2 cmpfiles的簡單使用
用法:filecmp.cmpfiles(dir1,dir2,common[files...]),作用是對比dir1 和 dir2 目錄的差異,該方法會返回三個list,分別是匹配,不匹配,錯誤。
2.2.1 複製文件
1 # mkdir -p dir1 dir2 2 # cp lcmp.py vnc.conf vnc.conf.bak dir1/ 3 # cp lcmp.py vnc.conf dir2/
2.2.2 編寫python代碼
1 # cat lcmpfiles.py 2 3 #!/usr/bin/env python 4 5 import os 6 7 import filecmp 8 9 import sys 10 11 dir1 = input("Please enter a folder to match:") 12 13 dir2 = input("Please enter a folder to match:") 14 15 files = [] 16 17 while True: 18 19 local_files = input("Please enter the file to compare:[n/N Exit the input]") 20 21 if local_files == 'N' or local_files == 'n': 22 23 break 24 25 elif local_files == '': 26 27 continue 28 29 else : 30 31 files.append(local_files) 32 33 try: 34 35 os.path.exists(dir1) 36 37 os.path.exists(dir2) 38 39 except: 40 41 print ("Pleae check the folder.") 42 43 sys.exit() 44 45 #print (filecmp.cmpfiles(dir1,dir2,files)[0]) 46 47 print ("It's file match:",filecmp.cmpfiles(dir1,dir2,files)[0]) 48 49 print ("The file does not match:",filecmp.cmpfiles(dir1,dir2,files)[1]) 50 51 print ("File does not exists:",filecmp.cmpfiles(dir1,dir2,files)[2])
2.2.3 用python3執行腳本(因為使用了input)
1 # python3 lcmpfiles.py 2 Please enter a folder to match:dir1 3 Please enter a folder to match:dir2 4 Please enter the file to compare:[n/N Exit the input]lcmp.py 5 Please enter the file to compare:[n/N Exit the input]vnc.conf 6 Please enter the file to compare:[n/N Exit the input]vnc.conf.bak 7 Please enter the file to compare:[n/N Exit the input]n 8 It's file match: ['lcmp.py', 'vnc.conf'] 9 The file does not match: [] 10 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 模擬環境
1 # ls dir1/ dir2/ 2 dir1/: 3 hosts ld.so.conf sysconfig 4 5 dir2/: 6 hosts ld.so.conf sysconfig
其中,sysconfig 是一個目錄 hosts 和 ld.so.conf都是文件,且hosts內容不一致 sysconfig中的文件也不一樣
2.2.2 編寫python代碼
2.2.2.1 dircmp.report()
1 # cat simple_filecmp.py 2 3 #!/usr/bin/env python 4 5 import filecmp 6 7 dir1 = "/root/python/d_2_filecmp/cmp/dir2" 8 9 dir2 = "/root/python/d_2_filecmp/cmp/dir1" 10 11 dirobj = filecmp.dircmp(dir1,dir2) 12 13 print (dirobj.report())
2.2.2.2 執行腳本
1 # python simple_filecmp.py 2 diff /root/python/d_2_filecmp/cmp/dir2 /root/python/d_2_filecmp/cmp/dir1 3 Identical files : ['ld.so.conf'] 4 Differing files : ['hosts'] 5 Common subdirectories : ['sysconfig'] 6 None 7 [root@localhost cmp]# cat simple_filecmp.py
由上面的結果,我們可以看出,report只能比對腳本的首層目錄,而無法對子文件夾下的目錄進行匹配
2.2.2.3 report_full_closure()
1 # cat simple_filecmp_2.py 2 3 #!/usr/bin/env python 4 5 import filecmp 6 7 dir1 = "/root/python/d_2_filecmp/cmp/dir1/" 8 9 dir2 = "/root/python/d_2_filecmp/cmp/dir2/" 10 11 dirobj = filecmp.dircmp(dir1,dir2) 12 13 print (dirobj.report_full_closure())
2.2.2.4 執行腳本
1 diff /root/python/d_2_filecmp/cmp/dir1/ /root/python/d_2_filecmp/cmp/dir2/ 2 Identical files : ['ld.so.conf'] 3 Differing files : ['hosts'] 4 Common subdirectories : ['sysconfig'] 5 6 diff/root/python/d_2_filecmp/cmp/dir1/sysconfig /root/python/d_2_filecmp/cmp/dir2/sysconfig 7 ......
由此可見差別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
只在左邊出現的文件
1 # cat simple_filecmp_3.py 2 3 #!/usr/bin/env python 4 5 import filecmp 6 7 dir1 = "/root/python/d_2_filecmp/cmp/dir1/" 8 9 dir2 = "/root/python/d_2_filecmp/cmp/dir2/" 10 11 dirobj = filecmp.dircmp(dir1,dir2) 12 13 print (dirobj.diff_files)
執行結果
1 # ls dir1 dir2/ 2 dir1: 3 hosts ld.so.conf sysconfig teacher 4 5 dir2/: 6 hosts ld.so.conf sysconfig 7 [root@localhost cmp]# python simple_filecmp_3.py 8 ['teacher']
由上訴可見,當teacher只出現在dir1時,則會被抓取出來,所謂的left和right是相對於filecmp.dircmp而言的
dircmp.diff_files
返回不能匹配額文件
1 # cat simple_filecmp_3.py 2 3 #!/usr/bin/env python 4 5 import filecmp 6 7 dir1 = "/root/python/d_2_filecmp/cmp/dir1/" 8 9 dir2 = "/root/python/d_2_filecmp/cmp/dir2/" 10 11 dirobj = filecmp.dircmp(dir1,dir2) 12 13 print (dirobj.diff_files) 14 15 #print (dirobj.left_only)
執行結果
1 [root@localhost cmp]# ls dir1 dir2 2 dir1: 3 hosts ld.so.conf sysconfig teacher 4 5 dir2: 6 hosts ld.so.conf sysconfig 7 [root@localhost cmp]# python simple_filecmp_3.py 8 ['hosts'] 9 [root@localhost cmp]#
之前我們修改過hosts的文件,文件內容已經不一致,現在已經被抓取出來了
3.3.2 編寫自動備份腳本
1 # cat d_7_12_filecmp.py 2 #!/usr/bin/env python 3 4 import filecmp 5 import os 6 import sys 7 import shutil 8 9 source_files = "/root/python/d_2_filecmp/dir1" 10 target_files = "/root/python/d_2_filecmp/dir2" 11 12 def check_common_dirs(source_files,target_files): 13 dirsobj = filecmp.dircmp(source_files , target_files) 14 15 common_dirs_list = dirsobj.common_dirs 16 17 for common_line in common_dirs_list : 18 files_contrast('/'+source_files+'/'+common_line,'/'+target_files+'/'+common_line) 19 20 def files_contrast(dir1,dir2) : 21 22 dirobj = filecmp.dircmp(dir1,dir2) 23 24 no_exists_files = dirobj.left_only 25 no_diff_files = dirobj.diff_files 26 27 for exists_files in no_exists_files : 28 29 if os.path.isfile(exists_files) : 30 shutil.copyfile ('/'+dir1+'/'+exists_files , '/'+dir2+'/'+exists_files) 31 else : 32 print ("%s is dirctory" %(exists_files)) 33 os.makedirs('/'+dir2+'/'+exists_files) 34 print ("%s is mkdirs" %('/'+target_files+'/'+exists_files)) 35 36 try : 37 print ("values : %s %s" %('/'+dir1+'/'+exists_files , '/'+dir2+'/'+exists_files)) 38 files_contrast('/'+dir1+'/'+exists_files , '/'+dir2+'/'+exists_files) 39 except : 40 return 41 42 for diff_files in no_diff_files : 43 if os.path.isfile(diff_files) : 44 os.remove('/'+dir2+'/'+diff_files) 45 shutil.copyfile ('/'+dir1+'/'+diff_files , '/'+dir2+'/'+diff_files) 46 47 if os.path.exists(source_files) : 48 49 if os.path.exists(target_files) == "False" : 50 os.makedirs(target_files) 51 52 files_contrast(source_files,target_files) 53 check_common_dirs(source_files,target_files) 54 55 else : 56 print ("Soure files no exists") 57 sys.exit()
3.4 執行腳本輸出
3.4.1 查看文件
可知 dir2下沒有任何文件
1 # tree dir1/ dir2/ 2 dir1/ 3 ├── 123 4 │ └── 123456 5 ├── 4556 6 │ └── 789 7 │ └── d 8 ├── lcmp.py 9 ├── vnc.conf 10 └── vnc.conf.bak 11 dir2/ 12 13 3 directories, 5 files
3.4.2 執行腳本
1 root@localhost d_2_filecmp]# python d_7_12_filecmp.py 2 4556 is dirctory 3 //root/python/d_2_filecmp/dir2/4556 is mkdirs 4 values : //root/python/d_2_filecmp/dir1/4556 //root/python/d_2_filecmp/dir2/4556 5 789 is dirctory 6 //root/python/d_2_filecmp/dir2/789 is mkdirs 7 values : ///root/python/d_2_filecmp/dir1/4556/789 ///root/python/d_2_filecmp/dir2/4556/789 8 d is dirctory 9 //root/python/d_2_filecmp/dir2/d is mkdirs 10 values : ////root/python/d_2_filecmp/dir1/4556/789/d ////root/python/d_2_filecmp/dir2/4556/789/d 11 123 is dirctory 12 //root/python/d_2_filecmp/dir2/123 is mkdirs 13 values : //root/python/d_2_filecmp/dir1/123 //root/python/d_2_filecmp/dir2/123 14 123456 is dirctory 15 //root/python/d_2_filecmp/dir2/123456 is mkdirs 16 values : ///root/python/d_2_filecmp/dir1/123/123456 ///root/python/d_2_filecmp/dir2/123/123456
可以看出,備份的信息,前面的多個/可以不必理會,linux只識別一個/
3.4.3 查看備份效果
1 # tree dir1/ dir2/ 2 dir1/ 3 ├── 123 4 │ └── 123456 5 ├── 4556 6 │ └── 789 7 │ └── d 8 ├── lcmp.py 9 ├── vnc.conf 10 └── vnc.conf.bak 11 dir2/ 12 ├── 123 13 │ └── 123456 14 ├── 4556 15 │ └── 789 16 │ └── d 17 ├── lcmp.py 18 ├── vnc.conf 19 └── vnc.conf.bak 20 21 8 directories, 8 files
由上,可知,備份完全成功,針對於定時執行python腳本,可以將腳本寫入crontab中,開啟定時任務即可。