影刀RPA 文件比较与差异同步 影刀RPA 文件比较与差异同步作者林焱什么情况用什么需要对比两个文件夹找出差异——哪些文件新增了、哪些修改了、哪些删除了。或者同步两个目录让它们保持一致。在影刀RPA里用Python可以快速比较文件差异并执行同步操作。适用场景文件夹同步、代码部署、配置同步、备份验证、多电脑文件同步。怎么做拼多多店群自动化报活动上架文件夹差异比较importosimporthashlibdefcompare_directories(dir1,dir2,compare_contentTrue):比较两个文件夹的差异# 获取两个文件夹的文件列表files1get_file_list(dir1)files2get_file_list(dir2)# 比较结果added[]# dir2有但dir1没有新增removed[]# dir1有但dir2没有删除modified[]# 两边都有但内容不同same[]# 完全相同set1set(files1.keys())set2set(files2.keys())# 只在dir1中存在的forrel_pathinset1-set2:removed.append(rel_path)# 只在dir2中存在的forrel_pathinset2-set1:added.append(rel_path)# 两边都存在的forrel_pathinset1set2:ifcompare_content:hash1get_file_md5(os.path.join(dir1,rel_path))hash2get_file_md5(os.path.join(dir2,rel_path))ifhash1!hash2:modified.append(rel_path)else:same.append(rel_path)else:# 只比较大小和修改时间size1os.path.getsize(os.path.join(dir1,rel_path))size2os.path.getsize(os.path.join(dir2,rel_path))ifsize1!size2:modified.append(rel_path)else:same.append(rel_path)result{新增:added,删除:removed,修改:modified,相同:same}print(f比较结果:)print(f 新增:{len(added)}个)print(f 删除:{len(removed)}个)print(f 修改:{len(modified)}个)print(f 相同:{len(same)}个)returnresultdefget_file_list(root):获取目录下所有文件的相对路径files{}fordirpath,_,filenamesinos.walk(root):forfinfilenames:filepathos.path.join(dirpath,f)rel_pathos.path.relpath(filepath,root)files[rel_path]filepathreturnfilesdefget_file_md5(filepath):计算文件MD5hash_md5hashlib.md5()withopen(filepath,rb)asf:forchunkiniter(lambda:f.read(8192),b):hash_md5.update(chunk)returnhash_md5.hexdigest()# 使用diffcompare_directories(rC:\Project\v1,rC:\Project\v2)# 打印差异详情forcategory,filesindiff.items():iffilesandcategory!相同:print(f\n{category}:)forfinfiles[:10]:print(f{f})目录同步importshutildefsync_directories(source,target,directionsource_to_target,delete_extraTrue,dry_runFalse): 同步两个目录 direction: source_to_target 或 bidirectional delete_extra: 是否删除目标目录中源目录没有的文件 dry_run: 只显示不实际执行 diffcompare_directories(source,target)actions[]ifdirectionsource_to_target:# 新增复制到目标forrel_pathindiff[新增]:srcos.path.join(source,rel_path)dstos.path.join(target,rel_path)actions.append((复制(新增),src,dst))# 修改覆盖目标forrel_pathindiff[修改]:srcos.path.join(source,rel_path)dstos.path.join(target,rel_path)actions.append((覆盖(修改),src,dst))# 删除删除目标中多余的ifdelete_extra:forrel_pathindiff[删除]:dstos.path.join(target,rel_path)actions.append((删除(多余),None,dst))# 执行操作foraction,src,dstinactions:ifdry_run:print(f[预览]{action}:{dst})continuetry:ifaction.startswith(复制)oraction.startswith(覆盖):os.makedirs(os.path.dirname(dst),exist_okTrue)shutil.copy2(src,dst)print(f{action}:{dst})elifaction.startswith(删除):ifos.path.exists(dst):os.remove(dst)print(f{action}:{dst})exceptExceptionase:print(f 错误:{action}{dst}:{e})print(f\n同步完成:{len(actions)}个操作)# 使用# 预览不实际执行sync_directories(rC:\Source,rC:\Backup,dry_runTrue)# 实际同步sync_directories(rC:\Source,rC:\Backup,delete_extraTrue)文件内容差异defcompare_text_files(file1,file2):比较两个文本文件的内容差异importdifflibwithopen(file1,r,encodingutf-8)asf:lines1f.readlines()withopen(file2,r,encodingutf-8)asf:lines2f.readlines()# 生成差异differdifflib.unified_diff(lines1,lines2,fromfilefile1,tofilefile2,lineterm)diff_lineslist(differ)ifnotdiff_lines:print(文件内容完全相同)return[]print(f发现{len(diff_lines)}行差异:)forlineindiff_lines:print(line)returndiff_lines# 使用compare_text_files(rC:\Config\v1.json,rC:\Config\v2.json)影刀RPA文件同步流程【设置变量】 source rC:\Project\Current target rD:\Backup\Project 【执行Python代码】 # 先预览差异 diff compare_directories(source, target) yd_var[diff] diff 【输出信息】 新增: X个文件 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/c6934a038f794c7b99a569ffafc5f886.png#pic_center) 修改: Y个文件 删除: Z个文件 【执行Python代码】 # 执行同步 sync_directories(source, target, delete_extraTrue) 【输出信息】 同步完成有什么坑坑1路径分隔符不一致# 问题Windows用\Linux用/比较时路径不匹配# 解决统一用os.path.relpath获取相对路径rel_pathos.path.relpath(filepath,root)[video(video-wMz03ve4-1784312067445)(type-csdn)(url-https://live.csdn.net/v/embed/526817)(image-https://v-blog.csdnimg.cn/asset/1d3c3709da119dd8c13ab01e9b282520/cover/Cover0.jpg)(title-TEMU店群矩阵自动化运营核价报活动)]# 这个方法会自动处理路径分隔符坑2大文件MD5比较太慢# 问题几百个文件每个都算MD5很慢# 解决先比大小大小不同直接判为修改相同再算MD5defquick_compare(file1,file2):快速比较两个文件size1os.path.getsize(file1)size2os.path.getsize(file2)ifsize1!size2:returnFalse# 大小不同内容肯定不同# 大小相同再比MD5returnget_file_md5(file1)get_file_md5(file2)坑3同步时文件被占用# 问题复制文件时目标文件正被使用# 解决跳过并记录try:shutil.copy2(src,dst)![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/024d2de87ead4b3ba6e5de88e240cf05.png#pic_center)exceptPermissionError:print(f文件被占用跳过:{dst})failed.append(dst)坑4删除文件误删# 问题delete_extraTrue时删除了不该删的文件# 解决先dry_run预览确认后再执行# 第一步预览sync_directories(source,target,dry_runTrue)# 人工检查输出# 第二步确认后执行sync_directories(source,target,delete_extraTrue)坑5符号链接导致循环# 问题目录中有符号链接指向父目录递归无限循环# 解决跳过符号链接fordirpath,dirnames,filenamesinos.walk(root):# 跳过符号链接目录![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/ebed049ecf1441deae267437b946513b.png#pic_center)![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/9ac7251b8adf44779b7c970ea06da629.png#pic_center)![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/39d09f04bd1b4e19828f4f7314e5bab8.png#pic_center)dirnames[:][dfordindirnamesifnotos.path.islink(os.path.join(dirpath,d))]