# 作用: 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