
桌面应用【免费下载链接】dupeguruFind duplicate files项目地址https://gitcode.com/gh_mirrors/du/dupeguru点击查看免费下载hscommon/conflict.py是 dupeGuru 项目中专门处理目标位置文件名冲突的通用工具模块它以[000]形式的方括号编号前缀为核心协议对外提供get_conflicted_name、get_unconflicted_name、is_conflicted三个命名工具函数以及smart_move/smart_copy两个带冲突消解的移动/复制操作。本文结合 hscommon/conflict.py、hscommon/tests/conflict_test.py 以及它在 core/app.py、core/results.py 中的真实调用点系统讲解其命名规则、边界行为、底层实现原理与在 dupeGuru 去重工作流中的实战位置。一、模块定位dupeGuru 中名字冲突的统一解决方案在 dupeGuru 的实际使用场景中把重复文件移动/复制到某个目标文件夹是最核心的操作之一。当目标目录里已经存在同名文件时直接覆盖会造成数据丢失直接报错则会让批处理流程中断。hscommon.conflict模块给出的答案是不覆盖、不报错而是自动为目标文件名加上一个[000]形式的方括号编号前缀从而让每个文件都能落盘。模块文档字符串hscommon/conflict.py给出了这一设计的官方定义When you have to deal with names that have to be unique and can conflict together, you can use this module that deals with conflicts by prepending unique numbers in[]brackets to the name.即当你需要处理必须唯一、但可能相互冲突的名字时可以借助本模块通过向名字前置[]方括号内的唯一编号来消解冲突。这一设计有两个关键特点幂等可逆get_conflicted_name生成的前缀可以通过get_unconflicted_name干净地剥除恢复到原始文件名对用户友好[000]前缀直观表明了这是一个冲突副本且按[000]、[001]……递增用户在文件管理器中一眼就能看出冲突顺序。二、核心命名协议[三位数字]前缀与正则定义冲突命名协议由模块顶部的正则常量re_conflict定义hscommon/conflict.pyre_conflict re.compile(r^\[\d{3}\d*\] )这条正则的含义与约束是正则片段含义约束说明^锚定字符串开头只有出现在名字最开头的方括号编号才被识别为冲突前缀\[\d{3}\d*\]方括号内至少 3 位数字匹配[123]但不匹配[12]\d*允许 4 位及以上如[1000]尾随空格前缀与文件名之间必须有一个空格[000]foo不算冲突名也就是说is_conflicted([000] foobar)返回True而is_conflicted([000]foobar)无空格、is_conflicted([000a] foobar)含字母、is_conflicted(foo [000] bar)编号不在开头都返回False。对应断言可在 hscommon/tests/conflict_test.py 中查到。选择至少 3 位数字的原因从测试中可以看出冲突计数可能超过 99如[1000] bar三位起步保证了编号的稳定递增空间同时避免把[12]这类普通文件名误判为冲突名。三、三个命名工具函数生成、剥离与判定3.1get_conflicted_name(other_names, name)生成不冲突的名字签名hscommon/conflict.pydef get_conflicted_name(other_names: List[str], name: str) - str:行为逻辑分三步自动去冲突先对name调用get_unconflicted_name剥离已有前缀——即使传入的名字本身就是[001] bar也会先还原成bar再重新编号避免前缀叠加查重如果剥离后的名字不在other_names中直接原样返回递增编号否则从i 0开始依次尝试[%03d] %s % (i, name)即[000] name、[001] name……直到找到一个不在other_names中的名字。%03d格式说明编号至少 3 位、不足补零而超过 999 时自然扩展为 4 位如[1000]这也与正则\d{3}\d*的允许多位设计相呼应。测试用例验证了以下边界hscommon/tests/conflict_test.pyget_conflicted_name([bar], bar) # - [000] bar get_conflicted_name([bar, [000] bar], bar) # - [001] bar get_conflicted_name([bar], foobar) # - foobar无冲突 get_conflicted_name([], [000] foobar) # - foobar自动去冲突 get_conflicted_name([bar], [001] bar) # - [000] bar先还原再编号第 4 位数字的极端场景1000 个冲突同名文件也有专门测试覆盖hscommon/tests/conflict_test.py测试注释也坦承这种情形几乎没有机会发生但从协议上保证了正确性。3.2get_unconflicted_name(name)剥离冲突前缀签名hscommon/conflict.pydef get_unconflicted_name(name: str) - str: return re_conflict.sub(, name, 1)通过re_conflict.sub(, name, 1)把名字开头匹配到的方括号编号前缀含尾随空格替换为空且最多替换一次。其行为要点[000] foobar→foobar[9999] foobar→foobar多位编号同样剥离[000]foobar→ 原样返回无空格不匹配协议[000a] foobar→ 原样返回编号含非数字foo [000] bar→ 原样返回前缀不在开头foobar→ 原样返回。这保证了只有严格符合冲突协议的名字才会被还原普通文件名即使包含方括号也不会被误改。对应断言见 hscommon/tests/conflict_test.py。3.3is_conflicted(name)判定是否为冲突名签名hscommon/conflict.pydef is_conflicted(name: str) - bool: return re_conflict.match(name) is not None本质就是正则match是否命中match天然从字符串开头尝试匹配配合正则中的^双重锚定。True/False的判定用例与get_unconflicted_name完全对称见 hscommon/tests/conflict_test.py。四、智能移动与复制smart_move/smart_copy与底层_smart_move_or_copy命名工具之外模块还提供了两个开箱即用的文件操作smart_move移动与smart_copy复制。二者的公共逻辑集中在私有函数_smart_move_or_copyhscommon/conflict.pydef _smart_move_or_copy(operation: Callable, source_path: Path, dest_path: Path) - None: if dest_path.is_dir() and not source_path.is_dir(): dest_path dest_path.joinpath(source_path.name) if dest_path.exists(): filename dest_path.name dest_dir_path dest_path.parent newname get_conflicted_name(os.listdir(str(dest_dir_path)), filename) dest_path dest_dir_path.joinpath(newname) operation(str(source_path), str(dest_path))核心逻辑分三步目录归一如果目标是目录而源是文件则把目标路径改写为目标目录/源文件名这正是把文件移入目录场景冲突消解如果目标路径已存在则以目标目录的现有条目列表为other_names调用get_conflicted_name生成新名字拼接出新的目标路径执行操作把最终的源/目标路径交给传入的operation回调执行。4.1smart_move与smart_copy的区别smart_move(source_path, dest_path)hscommon/conflict.py回调为shutil.move移动后源文件不再存在smart_copy(source_path, dest_path)hscommon/conflict.py回调为shutil.copy但带递归目录复制与降级重试——若shutil.copy抛出OSError且errno为EISDIRLinux/macOS 的错误码 21或EACCESWindows 的错误码 13说明源是目录则改用shutil.copytree重新执行_smart_move_or_copy其他错误则原样向上抛出。这也是 hscommon/tests/conflict_test.py 中smart_copy对文件夹同样有效的原理所在。4.2 实战行为矩阵来自测试验证以测试夹具hscommon/tests/conflict_test.py临时目录下有foo、bar两个文件和一个dir目录为基准各场景结果如下调用结果smart_move(foo, baz)baz存在foo消失无冲突移动smart_copy(foo, baz)baz与foo同时存在无冲突复制smart_move(foo, dir)dir/foo存在foo消失目标为目录时并入其中smart_move(foo, bar)[000] bar存在foo消失目标文件已存在时生成冲突名连续两次把foo移入dirdir/foo与dir/[000] foo并存同名冲突编号递增上述断言分别位于 hscommon/tests/conflict_test.py。特别值得注意的是第二次同名移动得到[000] foo而非[001] foo因为此时目标目录中只有foo而无冲突名编号从 0 重新开始这与编号相对当前目录现有条目而言的设计一致。五、在 dupeGuru 中的真实调用链hscommon.conflict不是孤立工具它支撑着 dupeGuru 两大核心流程标记重复项的移动/复制与结果保存时的文件覆盖防护。5.1 移动/复制重复文件core/app.pycore/app.py顶部导入smart_move, smart_copycore/app.py在copy_or_move方法中根据用户选择分发core/app.pyif copy: smart_copy(source_path, dest_path) else: smart_move(source_path, dest_path) self.clean_empty_dirs(source_path.parent)该方法的调用链为用户在界面选择移动/复制标记项 →copy_or_move_markedcore/app.py启动异步任务并对每个被标记的重复项调用copy_or_move。目标路径的三种形态由 core/app.py 的DestType枚举决定DIRECT直接目标目录、RELATIVE重建相对路径、ABSOLUTE重建绝对路径。目标目录里已存在同名文件时冲突名由smart_copy/smart_move在底层自动解决——这正是 help/en/preferences.rst 中dupeGuru 通过向目标文件名前置编号来优雅处理命名冲突这一用户文档描述的实现支撑。另外hscommon/tests/conflict_test.py 之外core/tests/app_test.py 还通过monkeypatch把app.smart_copy替换为hscommon.conflict.smart_copy并统计调用次数验证了 UI 层触发与底层冲突处理模块之间的真实耦合。5.2 结果导出文件覆盖防护core/results.pycore/results.py导入get_conflicted_namecore/results.py在导出结果 XML 时如果目标路径恰好已是一个目录导致写入失败EISDIR/EACCES就通过get_conflicted_name(otherfiles, basename)生成冲突名后重试core/results.py。这说明命名工具函数同样服务于文件写入目标不可用时自动改名重试这一通用场景。六、设计要点与使用建议先剥离再编号get_conflicted_name内部强制先get_unconflicted_name保证了重复调用不会产生[000] [000] foo这类叠加前缀幂等性有测试背书协议识别靠正则is_conflicted/get_unconflicted_name都严格依赖re_conflict任何不满足开头 方括号 ≥3 位数字 空格的名字都不会被误伤目录与文件统一处理smart_move/smart_copy对目标为目录自动拼接源文件名对源为目录由smart_copy通过EISDIR/EACCES降级到copytree跨平台错误码差异Linux/macOS 的 21 与 Windows 的 13已在源码注释中说明hscommon/conflict.py编号相对目录现状冲突编号从 0 重新计数只保证与目标目录当前条目不重复不保证全局单调理解这一点有助于预测批量操作结果。对于需要在自有 Python 项目中复用此模式的开发者可直接将 hscommon/conflict.py 的三个命名函数与smart_move/smart_copy作为参考实现——它们依赖的标准库仅为re、os、shutil、errno与pathlib无任何第三方依赖且配套的 hscommon/tests/conflict_test.py 提供了完整的边界测试样例可直接移植。赞分享桌面应用【免费下载链接】dupeguruFind duplicate files项目地址https://gitcode.com/gh_mirrors/du/dupeguru点击查看免费下载相关推荐从崩溃到修复ImHex计算器模块括号表达式解析全解析从崩溃到修复ImHex计算器模块括号表达式解析全解析 你是否在使用ImHex计算器时遇到过括号表达式导致的崩溃问题本文将深入分析这一技术难题带你了解问题根桌面应用开发工具逆向工程PHP-CS-Fixer no_unneeded_braces 规则完全指南清理多余花括号与括号式命名空间PHP CS Fixer no_unneeded_braces 规则完全指南清理多余花括号与括号式命名空间 no_unneeded_braces 是 PHP开发工具代码质量静态分析Lint格式化解决Alacritty终端CtrlC冲突从复制文本到信号处理的完美配置解决Alacritty终端CtrlC冲突从复制文本到信号处理的完美配置 你是否也曾在Alacritty终端中遭遇这样的尴尬想复制选中的文本按下 Ctrl桌面应用上一篇Dear ImGui 快速上手实战手把手给 C 程序加一个实时调试面板下一篇readthedocs.org 团队结构与支持体系深度解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考