python 比较2个目录的子目录、子文件不同 作者:马育民 • 2024-04-06 11:36 • 阅读:10017 # 说明 比较 path1、path2目录,以path1为基准,比较path2目录 的 所有子目录、子文件是否相同 - 比较子目录规则:path1 存在的目录,但 path2 不存在,将其返回 - 比较子文件规则: - path1 存在的子文件,但 path2 不存在的,将其返回 - 如果path1和path2都有该文件,那么就比较sha512值,不相同就返回; ### 例子 path1 目录下: - 有目录:a、b - 文件:1.txt、2.txt path2 目录下: - 有目录:a、c - 文件:1.txt、3.txt 返回: - [b] - [2.txt] ### 提示 比较的是 **相对目录**,因为要比较的是两个不同目录,如果比较绝对路径,将全都不同 ### 代码 ``` import os,hashlib def diff_2path(path1 ,path2,ignores:list): ''' 以path1为基准,比较path2目录 的 所有子目录、子文件是否相同 :param path1: 源路径(全路径) :param path2: 目标路径(全路径) :param ignores 忽略的path1的子目录、子文件(注意是相对路径,适用于 path1 目录改动 或 改文件夹名) :return: 返回元组,第一个是 boolean,第二个元素是list,记录不同的目录,第三个元素是list,记录不同的文件 将 path1 存在的目录,但 path2 不存在的,返回 将 path1 存在的子文件,但 path2 不存在的,返回;如果path1和path2都有该文件,那么就比较sha512值,不相同就返回; 例子: path1 目录下,有目录:a、b,文件:1.txt、2.txt path2 目录下,有目录:a、c,文件:1.txt、3.txt 返回: [b] [2.txt] ''' path1 = os.path.normpath(path1) path2 = os.path.normpath(path2) # 将path1的子目录、子文件list中 files1 = [] # 要比较的目录放到该list中 dirs1 = [] # 遍历出要管理目录下的所有子文件、子文件夹 walk(path1 ,files1 ,dirs1,ignores) # 将path2的子目录、子文件list中 files2 = [] # 要比较的目录放到该list中 dirs2 = [] # 遍历出要管理目录下的所有子文件、子文件夹 walk(path2, files2, dirs2,ignores) # 截取相对路径 folder_name1 = os.path.basename(path1) files1_relpath = relpath_list(files1,folder_name1) dirs1_relpath = relpath_list(dirs1,folder_name1) folder_name2 = os.path.basename(path2) files2_relpath = relpath_list(files2,folder_name2) dirs2_relpath = relpath_list(dirs2,folder_name2) # 比较path1、path2的所有子目录----------------------- dirs_chng = [] for item in dirs1_relpath: if item in ignores: continue if item in dirs2_relpath: pass else: dirs_chng.append(item) # 比较path1、path2的所有子文件,要比较 sha512 files_chng = [] for i, item1 in enumerate(files1_relpath): diff = True # True表示不同;False表示相同 for j, item2 in enumerate(files2_relpath): if item1 == item2: sha512_item1 = sha512(files1[i]) sha512_item2 = sha512(files2[j]) if sha512_item1 != sha512_item2: diff = True else : diff = False break if diff: files_chng.append(item1) if len(dirs_chng) > 0 or len(files_chng) > 0: return True ,dirs_chng ,files_chng else: return False ,dirs_chng ,files_chng def walk(path,files:list,dirs:list,ignores:list): ''' 遍历文件夹、文件(不包含版本库文件件) :param path: :param files: 保存文件 :param dirs: 保存目录 :param ignores 忽略的path1的子目录、子文件(注意是相对路径,适用于 path1 目录改动 或 改文件夹名) :return: ''' path = os.path.normpath(path) # 将 ignore 截取相对路径 current_folder = os.path.basename(path) for item in os.scandir(path): item_relpath = relpath(item.path, current_folder) if item_relpath in ignores: continue if item.is_dir(): # print("目录:",item.path) dirs.append(item.path) walk(item.path,files,dirs,ignores) elif item.is_file(): # print("文件:",item.path) files.append(item.path) def relpath(path,start): ''' 从start开始计算相对路径(不包含start) 替代 os.path.relpath(path[, start]) :param path: :param start: :return: ''' path = os.path.normpath(path) if start == "": return path # print(path) path = path.replace("\\","/") # print(path) new_parts = [] parts = path.split("/") append_tag = False for item in parts: if item == start: append_tag = True continue if append_tag: new_parts.append(item) if len(new_parts) == 0: raise ValueError("["+path+"] 不包含 ["+start+"]") new_path = "/".join(new_parts) new_path = os.path.normpath(new_path) return new_path def relpath_list(paths,start): ''' 从start开始计算相对路径(不包含start) 替代 os.path.relpath(path[, start]) :param paths: list类型,路径 :param start: :return: ''' ret = [] for item in paths: rel = relpath(item,start) ret.append(rel) return ret def sha512(path): # hashlib.sha512() or hashlib.md5() algorithm = hashlib.sha512() with open(path, 'rb') as f: algorithm.update(f.read()) return algorithm.hexdigest() if __name__ == "__main__": path1 = r"C:\Users\mym\Desktop\重庆发票2" path2 = r"C:\Users\mym\Desktop\重庆发票2\.fvm版本库\backup\2\data" ignore = [r"C:\Users\mym\Desktop\重庆发票2\.fvm版本库"] res,dirs_diff,files_diff = diff_2path(path1,path2,ignore) print(res) print(dirs_diff) print(files_diff) ``` 原文出处:http://malaoshi.top/show_1IX7SZsT6B0j.html