天天看點

檔案與目錄差異對比方法

環境:

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

<code>&gt;&gt;&gt; </code><code>import</code> <code>filecmp</code>

<code>&gt;&gt;&gt; filecmp.</code><code>cmp</code><code>(</code><code>"/root/dir1/f1"</code><code>,</code><code>"/root/dir2/f1"</code><code>)</code>

<code>True</code>

<code>&gt;&gt;&gt; filecmp.</code><code>cmp</code><code>(</code><code>"/root/dir1/f1"</code><code>,</code><code>"/root/dir2/f5"</code><code>)</code>

<code>False</code>

多檔案對比:采用filecmp.cmpfiles(dir1, dir2, common[, shallow])方法,對比dir1與dir2目錄給定的檔案清單。該方法傳回檔案名的三個清單,分别為比對、不比對、錯誤。比對為包含比對的檔案的清單,不比對反之,錯誤清單包括了目錄不存在檔案、不具備讀權限或其他原因導緻的不能比較的檔案清單。

先建立一些檔案:

<a href="https://s5.51cto.com/wyfs02/M01/06/2A/wKiom1mylGnxXlP4AABAULk2v-A832.png" target="_blank"></a>

代碼:

<code>&gt;&gt;&gt; filecmp.cmpfiles(</code><code>"/root/dir1"</code><code>,</code><code>"/root/dir2"</code><code>,[</code><code>'f1'</code><code>,</code><code>'f2'</code><code>,</code><code>'f3'</code><code>,</code><code>'f4'</code><code>,</code><code>'f5'</code><code>])</code>

<code>([</code><code>'f1'</code><code>, </code><code>'f2'</code><code>, </code><code>'f3'</code><code>, </code><code>'f4'</code><code>], [], [</code><code>'f5'</code><code>])</code>

目錄對比:通過dircmp(a, b[, ignore[, hide]])類建立一個目錄比較對象,其中a和b是參加比較的目錄名。ignore代表檔案名忽略的清單,并預設為['RCS', 'CVS', 'tags'];hide代表隐藏的清單,預設為[os.curdir,os.pardir]。dircmp類可以獲得目錄比較的詳細資訊,如隻有在a目錄中包括的檔案、a與b都存在的子目錄、比對的檔案等,同時支援遞歸。

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

<code>#!/usr/bin/env python</code>

<code>#-*—coding:utf-8-*-</code>

<code>#2017,9,7</code>

<code>import</code> <code>filecmp</code>

<code>a </code><code>=</code> <code>"/root/dir1"</code> <code>#定義左目錄</code>

<code>b </code><code>=</code> <code>"/root/dir2"</code> <code>#定義右目錄</code>

<code>dirobj </code><code>=</code> <code>filecmp.dircmp(a,b,[</code><code>'1.py'</code><code>]) </code><code>#目錄比較,忽略1.py檔案。</code>

<code>dirobj.report() </code><code>#比較目前指定目錄中的内容</code>

<code>dirobj.report_full_closure() </code><code>#遞歸比較所有指定目錄的内容</code>

<code>dirobj.report_partial_closure() </code><code>#比較目前指定目錄以及第一級目錄中的内容</code>

<code>print</code> <code>"_"</code><code>*</code><code>50</code>

<code>print</code> <code>"left_list:"</code> <code>+</code> <code>str</code><code>(dirobj.left_list) </code><code>#左目錄</code>

<code>print</code> <code>"right_list:"</code><code>+</code><code>str</code><code>(dirobj.right_list) </code><code>#右目錄</code>

<code>print</code> <code>"commom:"</code><code>+</code><code>str</code><code>(dirobj.common) </code><code>#兩邊共同存在的目錄</code>

<code>print</code> <code>"left_only:"</code><code>+</code><code>str</code><code>(dirobj.left_only) </code><code>#隻在左目錄中的檔案或者目錄</code>

<code>print</code> <code>"right_only:"</code><code>+</code><code>str</code><code>(dirobj.right_only)  </code><code>#隻在右目錄中的檔案或者目錄</code>

<code>print</code> <code>"common_dirs:"</code><code>+</code><code>str</code><code>(dirobj.common_dirs)</code><code>#兩邊目錄都存在的子目錄</code>

<code>print</code> <code>"common_files:"</code><code>+</code><code>str</code><code>(dirobj.common_files) </code><code>#兩邊目錄都存在的檔案</code>

<code>print</code> <code>"common_funny:"</code><code>+</code><code>str</code><code>(dirobj.common_funny) </code><code>#兩邊目錄都存在的目錄</code>

<code>print</code> <code>"same_files:"</code><code>+</code><code>str</code><code>(dirobj.same_files) </code><code>#比對相同的檔案</code>

<code>print</code> <code>"diff_files:"</code> <code>+</code> <code>str</code><code>(dirobj.diff_files) </code><code>#不比對的檔案</code>

<code>print</code> <code>"funny_files:"</code> <code>+</code> <code>str</code><code>(dirobj.diff_files) </code><code>#兩邊目錄中都存在,但是無法比較的檔案</code>

執行結果:

<code>diff</code> <code>/root/dir1</code> <code>/root/dir2</code>

<code>Only </code><code>in</code> <code>/root/dir2</code> <code>: [</code><code>'f5'</code><code>]</code>

<code>Identical files : [</code><code>'f1'</code><code>, </code><code>'f2'</code><code>, </code><code>'f3'</code><code>, </code><code>'f4'</code><code>]</code>

<code>__________________________________________________</code>

<code>left_list:[</code><code>'f1'</code><code>, </code><code>'f2'</code><code>, </code><code>'f3'</code><code>, </code><code>'f4'</code><code>]</code>

<code>right_list:[</code><code>'f1'</code><code>, </code><code>'f2'</code><code>, </code><code>'f3'</code><code>, </code><code>'f4'</code><code>, </code><code>'f5'</code><code>]</code>

<code>commom:[</code><code>'f1'</code><code>, </code><code>'f2'</code><code>, </code><code>'f3'</code><code>, </code><code>'f4'</code><code>]</code>

<code>left_only:[]</code>

<code>right_only:[</code><code>'f5'</code><code>]</code>

<code>common_dirs:[]</code>

<code>common_files:[</code><code>'f1'</code><code>, </code><code>'f2'</code><code>, </code><code>'f3'</code><code>, </code><code>'f4'</code><code>]</code>

<code>common_funny:[]</code>

<code>same_files:[</code><code>'f1'</code><code>, </code><code>'f2'</code><code>, </code><code>'f3'</code><code>, </code><code>'f4'</code><code>]</code>

<code>diff_files:[]</code>

<code>funny_files:[]</code>

實踐:效驗源與備份目錄差異

源代碼:

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

<code>#coding:utf-8</code>

<code>import</code> <code>os</code>

<code>import</code> <code>sys</code>

<code>import</code> <code>re</code>

<code>import</code> <code>shutil</code>

<code>holderlist</code><code>=</code><code>[]</code>

<code>def</code> <code>compareme(dir1,dir2):</code>

<code>        </code><code>dircomp </code><code>=</code> <code>filecmp.dircmp(dir1,dir2)</code>

<code>        </code><code>only_in_one </code><code>=</code> <code>dircomp.left_only </code><code>#源目錄新檔案或目錄(隻在左目錄中的檔案或者目錄)</code>

<code>        </code><code>diff_in_one </code><code>=</code> <code>dircomp.diff_files </code><code>#不比對檔案,源目錄檔案已經發生變化</code>

<code>        </code><code>dirpath </code><code>=</code> <code>os.path.abspath(dir1) </code><code>#擷取源目錄的絕對路徑。</code>

<code>        </code><code>#将更新檔案名或者目錄追加到holderlist</code>

<code>        </code><code>[holderlist.append(os.path.abspath(os.path.join(dir1,x))) </code><code>for</code> <code>x </code><code>in</code> <code>only_in_one]</code>

<code>        </code><code>[holderlist.append(os.path.abspath(os.path.join(dir1,x))) </code><code>for</code> <code>x </code><code>in</code> <code>diff_in_one]</code>

<code>        </code><code>if</code> <code>len</code><code>(dircomp.common_dirs) &gt; </code><code>0</code><code>:</code>

<code>                </code><code>for</code> <code>item </code><code>in</code> <code>dircomp.common_dirs:</code>

<code>        </code><code>return</code> <code>holderlist</code>

<code>def</code> <code>main():</code>

<code>        </code><code>if</code> <code>len</code><code>(sys.argv) &gt; </code><code>2</code><code>:</code>

<code>                </code><code>dir1 </code><code>=</code> <code>sys.argv[</code><code>1</code><code>]</code>

<code>                </code><code>dir2 </code><code>=</code> <code>sys.argv[</code><code>2</code><code>]</code>

<code>        </code><code>else</code><code>:</code>

<code>                </code><code>print</code> <code>"usage:"</code><code>,sys.argv[</code><code>0</code><code>],</code><code>"datadir backupdir"</code>

<code>                </code><code>sys.exit()</code>

<code>        </code><code>source_files </code><code>=</code> <code>compareme(dir1,dir2) </code><code>#對比源目錄與備份目錄</code>

<code>        </code><code>dir1 </code><code>=</code> <code>os.path.abspath(dir1)</code>

<code>        </code><code>if</code> <code>not</code> <code>dir2.endswith(</code><code>'/'</code><code>):</code>

<code>                </code><code>dir2 </code><code>=</code> <code>dir2</code><code>+</code><code>'/'</code>

<code>        </code><code>dir2 </code><code>=</code> <code>os.path.abspath(dir2)</code>

<code>        </code><code>destination_files </code><code>=</code> <code>[]</code>

<code>        </code><code>createdir_bool </code><code>=</code><code>False</code>

<code>        </code><code>for</code> <code>item </code><code>in</code> <code>source_files: </code><code>#周遊傳回的差異檔案或者目錄清單</code>

<code>                </code><code>destination_dir </code><code>=</code> <code>re.sub(dir1,dir2,item) </code><code>#将源目錄差異路徑清單對應替換成備份目錄</code>

<code>                </code><code>destination_files.append(destination_dir)</code>

<code>                </code><code>if</code> <code>os.path.isdir(item):           </code><code>#如果差異路徑為目錄且不存在,則在備份目錄中建立</code>

<code>                        </code><code>if</code> <code>not</code> <code>os.path.exists(destination_dir):</code>

<code>                                </code><code>os.makedirs(destination_dir)</code>

<code>                                </code><code>createdir_bool </code><code>=</code> <code>True</code> <code>#再一次調用compareme函數标記</code>

<code>        </code><code>if</code> <code>createdir_bool:</code>

<code>                </code><code>destination_files </code><code>=</code> <code>[]</code>

<code>                </code><code>source_files</code><code>=</code><code>[]</code>

<code>                </code><code>source_files</code><code>=</code><code>compareme(dir1,dir2)</code>

<code>                </code><code>for</code> <code>item </code><code>in</code> <code>source_files:</code>

<code>                        </code><code>destination_dir </code><code>=</code> <code>re.sub(dir1,dir2,item)</code>

<code>                        </code><code>destination_files.append(destination_dir)</code>

<code>        </code><code>print</code> <code>"updata item:"</code>

<code>        </code><code>print</code> <code>source_files </code><code>#輸出更新清單清單</code>

<code>        </code><code>copy_pair </code><code>=</code> <code>zip</code><code>(source_files,destination_files) </code><code>#将源目錄與備份目錄檔案拆分成元組</code>

<code>        </code><code>for</code> <code>item </code><code>in</code> <code>copy_pair:</code>

<code>                </code><code>if</code> <code>os.path.isfile(item[</code><code>0</code><code>]): </code><code>#判斷是否為檔案,是則進行複制</code>

<code>                        </code><code>shutil.copyfile(item[</code><code>0</code><code>],item[</code><code>1</code><code>])</code>

<code>if</code> <code>__name__</code><code>=</code><code>=</code><code>'__main__'</code><code>:</code>

<code>        </code><code>main()</code>

<a href="https://s3.51cto.com/wyfs02/M01/06/2A/wKiom1myllng5ONdAAAn_dj3n2c260.png" target="_blank"></a>

總結\注意\拓展:

總結:

本次學習不僅學會了檔案備份的效驗,而且學習到了一個文法:

<code> </code><code>[holderlist.append(os.path.abspath(os.path.join(dir1,x))) </code><code>for</code> <code>x </code><code>in</code> <code>only_in_one]</code>

<code> </code><code>#正常寫法</code>

<code> </code><code>for</code> <code>x </code><code>in</code> <code>only_in_one:</code>

<code>     </code><code>holderlist.append(os.path.abspath(os.path.join(dir1,x)))</code>

注意:

在寫程式的時候一定要注意縮進,不然容易報錯,我在寫下面這句的時候就老報文法錯誤,做後讓别人打一遍,我複制一下才成功:

<code>return</code> <code>holderlist</code>

拓展:

re.sub是re子產品重要的組成部分,并且功能也非常強大,主要功能實作正則的替換

re.sub定義: 

sub(pattern, repl, string, count=0, flags=0)

解釋:

pattern:為表示正則中的模式字元串, 

repl為replacement,被替換的内容,repl可以是字元串,也可以是函數。 

string為正規表達式比對的内容。 

count:由于正規表達式比對到的結果是多個,使用count來限定替換的個數(順序為從左向右),預設值為0,替換所有的比對到的結果。 

flag是比對模式,可以使用按位或’|’表示同時生效,也可以在正規表達式字元串中指定。

<code>&gt;&gt;&gt;</code><code>import</code> <code>re</code>

<code>&gt;&gt;&gt;re.sub(r</code><code>'\w+'</code><code>,</code><code>'10'</code><code>,</code><code>"ji 43 af,geq"</code><code>,</code><code>2</code><code>,flags</code><code>=</code><code>re.I)</code>

<code>&gt;&gt;&gt;</code><code>'10 10 af,geq'</code>

shutil子產品:

詳情參考:http://blog.csdn.net/xmnathan/article/details/36217631

參考資料1:百度知道

參考資料2:網絡資源

參考資料3:《Python自動化運維技術與最佳實踐》-劉天斯 著

<a href="https://s5.51cto.com/wyfs02/M00/06/2A/wKiom1myl5zgGMuPAAQF1aT1ixQ567.png" target="_blank"></a>

本文轉自 天道酬勤VIP 51CTO部落格,原文連結:http://blog.51cto.com/tdcqvip/1963827