前言
這個程序陸陸續續開發了幾天,正好我在學Python,就一邊做一邊學,倒是學到不少東西。
不得不說python是快速開發的好工具。
程序做了一些改進,這兩天又忙着畢設,現在才想起來發到博客上。想想回頭github也要啟用起來,不能繼續荒廢了……
如果嫌運行python程序不方便的話,可以直接使用exe可執行文件版本。
exe發布器在這里:使用pyInstaller發布PathMerge的exe版本(py轉換成exe)
廢話不多說,我介紹一下這個工具。
應用場景
在日常使用中,我們往往需要把一個文件夾拷到另一個文件夾下面,做一些修改之后,再將改動的文件夾合並回去。
例如,從優盤中把一個要用的文件夾拷到電腦上,在pc機上工作,之后你需要將修改后的文件夾再拷回優盤中帶走。
這個時候問題來了。
如果你做的修改不多,我們可以簡單的把修改的文件復制回去,這個時候你清楚的記得你到底修改了哪些文件。
但是如果你對很多文件做了改動,並且還創建了幾個文件或者文件夾,導致目錄結構變得十分復雜,最后你自己都記不起來到底哪些文件做了哪些改動,目錄做了哪些更新,這個時候你要把文件夾合並回去就有些凌亂了……
So,你需要一個工具去幫你記憶你做的改動,自動的幫你合並文件夾,並且不會丟失任何文件。
這個時候這個小工具就可以派上用場了~
下面演示一下怎么用。
使用演示
現在有兩個工作空間
工作空間1是你之前做好的一個工程或者文件夾,里面放滿了文件,目錄結構復雜。
詳細目錄:
工作空間2是你現在要工作的目錄,現在是空的。
我們把要用的文件夾拷過來
並在里面做一些改動。
這里不放圖了,總之我創建了一個文件夾,創建了兩個文件,修改了三個文件……現在目錄結構變成這樣:
大家看到,1/下多了一個文件夾33,里面多了兩個文件111.txt和222.txt,我還修改了一個txt文件,一個ppt文件和一個word文件。
下面運行PathMerge:
輸入A目錄(修改的文件夾)和B目錄(原文件夾),要將A==>B,A合並到B。
回車開始合並:
合並成功!
合並的記錄都列在上面了,如果名稱相同的文件會將舊文件創建一個副本,修改后的文件直接復制過去,程序中沒有刪除文件的代碼,可放心食用。
上圖可知復制了三個文件,創建了三個舊文件副本,另外復制了創建的目錄。
將工作空間2中1文件做的所有改動都包含了進去。
以上,就是PathMerge的使用演示。
代碼
1 # coding=gbk
2
3 # PathMerge.py
4 # 作者:freecode
5 # 創建時間:2016.4.9 20:15
6 # 作用:
7 # 合並並兩個目錄/文件夾。
8 # 將目錄A合並到目錄B,同級目錄下,
9 # 將A中有,B中沒有的目錄完全復制到B中;
10 # 將A中沒有,B中有的目錄不做改動;
11 # 將A中做了修改的文件,在B的同級目錄下創建一個副本。(注意不是覆蓋)
12 # 13 # 適應場景:
14 # 一般A是從B復制過來的文件夾,做了修改后,想合並回B。
15 # 這樣在A中做的一些改動我們就不知道了,這個程序的作用是,
16 # 將A中修改的部分在B中更新。
17 # 18 # 版本:
19 # 將修改后的文件完全復制過去
20 # 舊的文件創建副本
21 # 基於文件的MD5值判斷是否修改過
22 # 23
24 import os 25 import shutil 26 import time 27 import hashlib 28 import sys 29
30 def Help(): # 輸出幫助文檔
31 print """
32 PathMerge.py 33 作者:freecode 34 創建時間:2016.4.9 20:15 35 作用: 36 合並並兩個目錄/文件夾。 37 將目錄A合並到目錄B,同級目錄下, 38 將A中有,B中沒有的目錄完全復制到B中; 39 將A中沒有,B中有的目錄不做改動; 40 將A中做了修改的文件,在B的同級目錄下創建一個副本。(注意不是覆蓋) 41
42 適應場景: 43 一般A是從B復制過來的文件夾,做了修改后,想合並回B。 44 這樣在A中做的一些改動我們就不知道了,這個程序的作用是, 45 將A中修改的部分在B中更新。 46
47 版本: 48 將修改后的文件完全復制過去 49 舊的文件創建副本 50 基於文件的MD5值判斷是否修改過 51 """
52
53 def GetFileMd5(filename): # 計算文件的md5值
54 if not os.path.isfile(filename): 55 return
56 myhash = hashlib.md5() 57 f = file(filename,'rb') 58 while True: 59 b = f.read(8096) 60 if not b : 61 break
62 myhash.update(b) 63 f.close() 64 return myhash.hexdigest() 65
66 def isModify(A_file,B_file): # 判斷兩個文件是否相同,如果不同,表示修改過
67 # 參數需是絕對路徑
68 return GetFileMd5(A_file) != GetFileMd5(B_file) 69
70 def Stamp2Time(Stamp): # 將時間戳轉換成時間顯示格式
71 timeArray = time.localtime(Stamp) 72 Time = time.strftime("%Y年%m月%d日 %H時%M分%S秒 舊文件副本", timeArray) 73 return Time 74
75 def Merge(A_path,B_path): # 合並兩個目錄
76 B_paths = os.listdir(B_path) # 獲取當前B中的目錄結構
77 for fp in os.listdir(A_path): # 遍歷當前A目錄中的文件或文件夾
78 A_new_path = os.path.join(A_path,fp) # A中的文件或目錄
79 B_new_path = os.path.join(B_path,fp) # B中對應的文件或路徑,不一定存在
80
81 if os.path.isdir(A_new_path): # A中的目錄
82 if os.path.exists(B_new_path): # 如果在B中存在
83 Merge(A_new_path,B_new_path) # 繼續合並下一級目錄
84 else: # 如果在B中不存在
85 print '[目錄]\t%s ===> %s' %(A_new_path,B_new_path) 86 shutil.copytree(A_new_path,B_new_path) # 完全復制目錄到B
87
88 elif os.path.isfile(A_new_path): # A中的文件
89 if os.path.exists(B_new_path): # 如果在B中存在
90 s = os.stat(B_new_path) 91 if isModify(A_new_path,B_new_path) == True: # 如果該文件修改過
92 # 創建副本
93 suffix = B_new_path.split('.')[-1] # 得到文件的后綴名
94 # 將B中原文件創建副本
95 B_copy_path = B_new_path[:-len(suffix)-1]+"(%s)."%(Stamp2Time(s.st_mtime))+suffix 96 print '[副本]\t%s ===> %s' %(A_new_path,B_copy_path) 97 shutil.copy2(B_new_path,B_copy_path) 98 # 將A中修改后文件復制過來
99 print '[文件]\t%s ===> %s' %(A_new_path,B_new_path) 100 shutil.copy2(A_new_path,B_new_path) 101 else: # 如果該文件沒有修改過
102 pass # 不復制
103
104 else: # 如果在B中不存在
105 # 將該文件復制過去
106 print '[文件]\t%s ===> %s' %(A_new_path,B_new_path) 107 shutil.copy2(A_new_path,B_new_path) 108
109 # 運行模式
110 if __name__=='__main__': 111 print """
112 歡迎使用PathMerge! 113 本程序將會把目錄A合並到目錄B,即 A ===> B 114 將A目錄中修改的內容在B目錄中更新 115 合並規則具體見 PathMerge.Help() 116 """
117 if len(sys.argv) == 1: 118 path1 = raw_input('請輸入A目錄:').strip() 119 path2 = raw_input('請輸入B目錄:').strip() 120 elif len(sys.argv) == 2: 121 path1 = sys.argv[1].strip() 122 print 'A目錄為:%s\n' % (path1) 123 path2 = raw_input('請輸入B目錄:').strip() 124 elif len(sys.argv) == 3: 125 path1 = sys.argv[1].strip() 126 print 'A目錄為:%s\n' % (path1) 127 path2 = sys.argv[2].strip() 128 print 'B目錄為:%s\n' % (path2) 129 else: 130 print 'ERROR:參數錯誤!\n參數最多有三個!\n'
131 raw_input('\n請按回車鍵(Enter)退出……') 132 sys.exit(0) 133 # 去除目錄的引號
134 if path1[0]=='\"': 135 path1 = path1[1:-1] 136 if path2[0]=='\"': 137 path2 = path2[1:-1] 138
139 print """
140 開始合並目錄 %s 141 到目錄 %s 142 %s ===> %s 143 """ %(path1,path2,path1,path2) 144
145 try: 146 print '合並中……'
147 Merge(path1,path2) 148 print ''
149 except Exception,e: 150 print '合並失敗!'
151 print '失敗原因:\n',e 152 else: 153 print '合並成功!'
154
155 raw_input('\n請按回車鍵(Enter)退出……') 156
工具特性
1、可識別加“”的目錄和不加“”的目錄。
2、使用MD5識別文件是否修改。
MD5識別文件的內容見上一篇博文:python計算文件的md5值
3、可傳遞參數,用來寫腳本。例:
4、原文件夾內的舊文件不會被刪除,而是創建一個帶有時間戳的副本。修改過的文件直接復制過去。
這樣不用擔心合並之后文件莫名其妙的丟失啦。使用該工具不會有文件刪除操作。
注意
Sorry,目前僅支持windows環境……
參考資料
原創聲明
Freecode# : www.cnblogs.com/yym2013