dupeGuru 核心文件系统抽象层 `core.fs` 深度解析:File/Folder 模型、三级哈希与 SQLite 元数据缓存
桌面应用【免费下载链接】dupeguruFind duplicate files项目地址https://gitcode.com/gh_mirrors/du/dupeguru点击查看免费下载core.fs是 dupeGuru 各版本标准版 SE、音乐版 ME、图片版 PE共用的文件系统抽象层它把磁盘上的文件与文件夹统一封装成带懒加载元数据大小、修改时间、全文摘要、局部摘要、采样摘要的File/Folder对象并通过 SQLite 缓存哈希结果是后续重复匹配见 core/engine.py的输入基础。本文以 help/en/developer/core/fs.rst 所指向的core.fs模块文档为骨架结合 core/fs.py 源码与其测试用例 core/tests/fs_test.py完整梳理该模块的公开 API、内部机制与扩展方式读完你将对 dupeGuru 扫描管线的数据源头有源码级的清晰认识并掌握自行扩展文件包装类的路径。模块定位为 dupeGuru 定制的文件系统抽象core.fs的前身是hsfs一个最初为 musicGuru 设计的文件系统封装库。在 core/fs.py 的头部注释第 9-12 行中明确记录了这次 fork 的动机hsfs对 dupeGuru 而言过度设计带来了不必要的复杂度和内存占用。因此本模块只保留扫描重复文件所必需的能力用统一的File对象包装文件用Folder对象包装目录且Folder继承自File保证两者在后续匹配代码中可互换所有元数据大小、mtime、摘要都懒加载首次访问时才从磁盘或缓存读取提供三级摘要策略全文 digest、局部 digest_partial、采样 digest_samples在准确性与 I/O 开销之间取得平衡通过 SQLiteFilesDB缓存路径 大小 mtime对应的摘要避免重复扫描时重复读盘。模块顶部还定义了一个重要的运行时选择哈希算法。源码第 26-34 行优先尝试导入xxhash并使用xxh128否则回退到标准库hashlib.md5try: import xxhash hasher xxhash.xxh128 except ImportError: import hashlib hasher hashlib.md5这意味着在没有安装xxhash的纯净环境中dupeGuru 自动退化为 MD5两种算法对上层代码完全透明。这一算法选择也体现在FilesDB的 schema 版本描述中Changed from md5 to xxhash if availablecore/fs.py。公开 API 一览模块通过__all__显式导出以下符号core/fs.py符号类型职责File类单个文件的包装持有扫描所需的元数据Folder类目录包装聚合其子项的大小与摘要get_file(path, fileclasses)函数将路径包装为合适的File子类实例get_files(path, fileclasses)函数扫描目录返回其中所有文件的File实例列表FSError异常基类文件系统操作错误的统一异常AlreadyExistsError异常目标已存在重命名/复制冲突InvalidPath异常路径无效InvalidDestinationError异常复制/移动操作的目标非法OperationError异常复制/移动/删除操作后的校验未通过此外模块内还定义了模块级单例filesdb FilesDB()core/fs.py所有File实例共享同一个摘要缓存连接。异常体系统一错误报告所有文件系统错误都派生自FSErrorcore/fs.py错误消息模板统一为An error has occured on {name} in {parent}。构造时可传入字符串、File实例或空值File实例会取用其name属性parent用于补充出错位置。四个子类分别覆盖了典型场景AlreadyExistsError{name} already exists in {parent}例如File.rename()发现目标路径已存在时抛出InvalidPath{name} is invalid.例如get_files()中os.scandir抛OSError时抛出InvalidDestinationError复制/移动操作的目标非法OperationErrorOperation on {name} failed.操作执行后校验未通过时抛出。这一设计让上层GUI 与扫描引擎可以用统一的except FSError捕获所有文件操作问题同时保留具体错误类型的细分能力。File懒加载元数据的核心对象File类core/fs.py)代表一个待扫描的文件其设计有三个关键点。1.__slots__与内存优化源码注释第 206-208 行记录了实测数据仅凭__slots__一项在大量文件场景下未读取过信息的文件可节省约 35% 内存读取属性后的收益甚至可达 70%。因此File显式声明了__slots__ (path, unicode_path, is_ref, words) tuple(INITIAL_INFO.keys())第 209 行把所有元数据字段固定下来INITIAL_INFO {size: 0, mtime: 0, digest: b, digest_partial: b, digest_samples: b}is_ref由扫描器在匹配前统一打标见 core/scanner.py 中get_dupe_groups的f.is_ref Falsewords则是文件名分词的结果由core.engine.getwords()写入。2. NOT_SET 哨兵与懒加载构造时第 211-221 行所有元数据字段先被置为模块级哨兵对象NOT_SET而不是初值__getattribute__重写第 226-236 行保证任何字段首次被访问时自动触发_read_info(field)去真正读取读取失败则记日志并回退到INITIAL_INFO中的默认值。例如首次访问f.size时才执行path.stat()首次访问f.digest时才计算全文摘要。这意味着扫描器按需读取字段避免对所有文件做无谓的磁盘 I/O。3. 三级摘要策略File提供三种摘要对应不同粒度的内容比对core/fs.py字段计算方式用途digest以CHUNK_SIZE1 MiB第 53 行分块流式读取整个文件逐块喂给哈希器最终确认内容的确定性全文比对digest_partial只读取固定偏移与长度PARTIAL_OFFSET_SIZE (0x4000, 0x4000)即文件 16 KiB 处起读 16 KiB快速初筛避免大文件全文哈希digest_samples采样文件 25% 处、60% 处各 1 MiB 及末尾 1 MiB_calc_digest_samples第 260-277 行超过大文件阈值时的二次粗筛配套的阈值常量第 55-59 行CHUNK_SIZE 1024 * 1024 # 1 MiB 分块 MIN_FILE_SIZE 3 * CHUNK_SIZE # 3 MiB低于此大小不做采样 PARTIAL_OFFSET_SIZE (0x4000, 0x4000)_read_info中还有两个关键回退逻辑若文件小于 partial 的读取窗口小于0x4000 0x4000digest_partial直接取全文digest第 289-290 行若文件大小不超过MIN_FILE_SIZE不如直接整体哈希digest_samples直接等于digest第 302-303 行。_calc_digest_samples采样时使用floor(size * 25 / 100)与floor(size * 60 / 100)定位 25%、60% 位置末尾用fp.seek(-CHUNK_SIZE, 2)读取最后 1 MiB第 260-277 行。4. 属性与方法File暴露三个便捷属性第 352-363 行extension通过hscommon.util.get_file_ext取扩展名、namepath.name、folder_pathpath.parent。公开方法包括can_handle(path)类方法第 321-324 行判断某路径是否可被本类包装——必须是非符号链接的普通文件not path.is_symlink() and path.is_file()这是后续get_file分派的判据exists()第 326-332 行安全地检查文件是否存在OSError一律当作不存在处理并记警告日志rename(newname)第 334-346 行重命名文件目标已存在抛AlreadyExistsErrorOSError或重命名后目标不存在抛OperationErrorget_display_info(group, delta)返回用于 GUI 展示的字典基类中raise NotImplementedError()由各版本子类实现见下文版本子类扩展。Folder目录的聚合语义Folder继承自Filecore/fs.py)文档字符串指出它拥有与File相同的 size/digest 信息但其值是其子项之和。核心差异在_read_info的重写size/mtimesize是所有子项子文件夹 直接文件size之和mtime取目录自身stat().st_mtime第 384-390 行digest 系列将_all_items()中每个子项的同名摘要按字节拼接后整体哈希第 391-403 行。源码注释强调了一个重要约束拼接顺序必须稳定——如果文件被移动到不同的子目录中应该产生不同的摘要因此先按f.path排序再拼接第 397-398 行。subfolders属性第 405-411 行用os.scandir惰性枚举直接子目录同样排除符号链接_all_items()则返回subfolders get_files(self.path)。can_handle第 413-415 行要求路径是非符号链接的目录与File.can_handle正好互补二者共同构成get_file的完整分派规则。FilesDBSQLite 摘要缓存为避免重复扫描同一批文件时反复计算摘要core.fs内置了基于 SQLite 的缓存FilesDBcore/fs.py模块级单例为filesdb。表结构files (path TEXT PRIMARY KEY, size INTEGER, mtime_ns INTEGER, entry_dt DATETIME, digest BLOB, digest_partial BLOB, digest_samples BLOB)第 104-105 行三种摘要分别存储查询键默认按path size mtime_ns精确命中缓存第 107 行select_query若ignore_mtime为True则退化为只按path size查询第 108 行、115 行get()每次都会现取path.stat()得到 size 与 mtime_ns第 152-155 行保证缓存与磁盘状态的一致性写入使用INSERT ... ON CONFLICT(path) DO UPDATE第 109-113 行实现 upsert同时更新 size、mtime_ns、entry_dt 与对应摘要版本升级schema_version 1_check_upgrade在连接时检测版本不匹配则重建表并记录描述第 129-145 行当前版本描述正是从 md5 切换到可用的 xxhash并发连接时传入check_same_threadFalse并配合Lock保护读写第 121-126 行commit()与close()也走同一把锁容错get/put的任何异常都只记logging.warning而不向上传播第 172-173 行、187-188 行缓存失败不阻塞扫描主流程。File._read_info的缓存流程很直接访问某摘要字段时先filesdb.get()未命中才计算并filesdb.put()例如第 285-308 行对digest_partial、digest、digest_samples的处理。工厂函数get_file与get_files两个工厂函数完成路径 → 包装对象的转换core/fs.pyget_file(path, fileclasses[File])遍历候选类返回第一个can_handle(path)为真的类的实例若全部不匹配则返回Noneget_files(path, fileclasses[File])os.scandir遍历目录对每个条目调用get_file聚合所有可包装对象遇到OSError抛InvalidPath并用assert前置校验所有fileclasses都是File的子类。这套类分派 can_handle判据的机制正是各版本扩展自定义文件类型图片、音频的挂载点。在扫描管线中的位置三级摘要如何被使用core.fs的摘要字段不是孤立存在而是与 core/scanner.py 和 core/engine.py 协同扫描器按大小阈值过滤文件后调用engine.getmatches_by_contents(files, bigsizeself.big_file_size_threshold)core/scanner.pygetmatches_by_contents先按size分组core/engine.py只对同尺寸组内两两比较比较顺序为从便宜到昂贵先比digest_partial只读了 16 KiB命中后再看是否超过bigsize——超过则进一步比digest_samples采样 3 处否则做全文digest比对core/engine.py。这样大文件在最坏情况下也只会在partial 命中后才付出全文哈希的成本。这一调用链证实了三级摘要各自扮演的初筛 → 二次粗筛 → 最终确认角色与core.fs中三者的实现一一对应。零字节文件会跳过哈希直接以 100% 匹配处理core/engine.py这与_calc_digest对空文件的处理是自洽的。版本子类扩展从基类到 SE/PE/MEcore.fs的设计目标是作为可扩展基类。dupeGuru 三个版本各自实现了get_display_info及补充字段标准版SEcore/se/fs.py 中的File/Folder只重写get_display_info调用模块函数get_display_info生成供 GUI 展示的字典name、folder_path、size、extension、mtime、percentage、words、dupe_count并可基于group.get_match_of(dupe)输出相对参考文件的 delta 值图片版PEcore/pe/photo.py 的Photo扩展了INITIAL_INFO新增dimensions与exif_timestampHANDLED_EXTS限定可处理扩展名png/jpg/jpeg/gif/bmp/tiff/tif/webpcan_handle在此基础上叠加扩展名判断并额外实现 EXIF 方向读取get_orientation方向 5-8 时交换宽高与get_blocks图片模糊匹配块平台相关音乐版MEcore/me/fs.py 的MusicFile继承fs.File同样扩展元数据与can_handle判据按文件扩展名与可读标签能力过滤。这些子类只需遵守can_handle决定分派、_read_info决定元数据、INITIAL_INFO声明新字段三个约定即可无缝接入get_file/get_files与扫描管线。测试验证行为被测试锁定的关键保证core/tests/fs_test.py 集中验证了本模块的若干核心不变量test_size_aggregates_subfilesFolder.size等于所有子文件大小之和test_digest_aggregate_subfiles_sorted与test_partial_digest_aggregate_subfile_sorted目录摘要 对按固定顺序dir1/dir2/dir3与根目录文件排列的各子项摘要再哈希验证了目录摘要有序拼接的实现约束测试还用urandom生成了 200 KiB、1 MiB、10 MiB 三种随机数据文件create_fake_fs_with_random_data覆盖了全文摘要、partial 摘要与采样摘要三种路径test_has_file_attrsFolder必须表现如文件拥有mtime属性且扩展名为空——即Folder继承自File的兼容性契约。小结core.fs是 dupeGuru 扫描管线的数据基石File/Folder以懒加载与__slots__控制内存开销三级摘要全文/局部/采样配合CHUNK_SIZE、MIN_FILE_SIZE、PARTIAL_OFFSET_SIZE等常量在准确性、CPU 与 I/O 间取得平衡FilesDB以路径 size mtime_ns为键的 SQLite 缓存避免重复计算get_file/get_files与can_handle构成可扩展的分派机制SE/PE/ME 三版本在此之上各自叠加领域字段。理解这一层也就理解了 dupeGuru 一切匹配逻辑文件名分词、内容比对、目录摘要背后的输入来源与性能设计。赞分享桌面应用【免费下载链接】dupeguruFind duplicate files项目地址https://gitcode.com/gh_mirrors/du/dupeguru点击查看免费下载相关推荐深度解析Graphcool数据库抽象层与数据建模核心技术深度解析Graphcool数据库抽象层与数据建模核心技术 引言传统数据库开发的痛点与Graphcool的解决方案 你是否还在为繁琐的数据库配置、复杂的ORM深入解析 AferoWandB 核心组件中的 Go 通用文件系统抽象层深入解析 AferoWandB 核心组件中的 Go 通用文件系统抽象层 Afero 是 Go 生态中一款强大且可扩展的文件系统抽象库为本地磁盘、内存、归档文机器学习深度学习数据可视化可观测性从行情到交易信号machine-learning-for-trading 的完整数据管道与最快上手路径从行情到交易信号machine learning for trading 的完整数据管道与最快上手路径 行情数据拿到手怎样才能变成能回测、敢上实盘的信号中音视频桌面应用上一篇终极Python Modbus解决方案pymodbus完整指南下一篇VersaViT社区贡献指南如何参与这个开源视觉编码器的开发与改进创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Windows 文件删不掉?用 File Locksmith 快速定位并释放被占用的进程

Windows 文件删不掉?用 File Locksmith 快速定位并释放被占用的进程

Windows 文件删不掉?用 File Locksmith 快速定位并释放被占用的进程 【免费下载链接】PowerToys Microsoft PowerToys is a collection of utilities that supercharge productivity and customization on Windows 项目地址: https://gitcode.com/GitHub_Trending…

2026/10/3 17:29:42 阅读更多 →
Linux系统编程-信号(黑马笔记)

Linux系统编程-信号(黑马笔记)

当一个进程跟另外一个进程发送信号后&#xff0c;接收信号的进程有以下几种行为&#xff1a;1.执行默认处理 2.忽略 3.捕捉后特定处理1.kill函数发送信号的函数#include <sys/types.h> #include <signal.h>int kill(pid_t pid, int sig);参数说明pid&#xff1a;指…

2026/10/3 17:29:37 阅读更多 →
5分钟上手:res-downloader 网络资源嗅探下载完整指南(视频号/抖音/m3u8/直播流)

5分钟上手:res-downloader 网络资源嗅探下载完整指南(视频号/抖音/m3u8/直播流)

5分钟上手&#xff1a;res-downloader 网络资源嗅探下载完整指南&#xff08;视频号/抖音/m3u8/直播流&#xff09; 【免费下载链接】res-downloader 视频号、小程序、抖音、快手、小红书、直播流、m3u8、酷狗、QQ音乐等常见网络资源下载! 项目地址: https://gitcode.com/Git…

2026/10/3 17:29:30 阅读更多 →

最新新闻

DFT谱分析实战:从参数选择到Python代码实现

DFT谱分析实战:从参数选择到Python代码实现

做信号处理这些年&#xff0c;我越来越觉得DFT&#xff08;离散傅里叶变换&#xff09;是数字信号处理里最“划算”的一笔投资。你花一晚上搞懂它&#xff0c;换来的是一辈子的频域视野。很多时域里看不出来的问题——比如两个很接近的频率成分、藏在噪声里的微弱周期信号、机械…

2026/10/3 18:15:11 阅读更多 →
Mask R-CNN Win10 可运行方案:纯Python替代CUDA算子

Mask R-CNN Win10 可运行方案:纯Python替代CUDA算子

简介&#xff1a;本资源是一套专为Windows 10平台适配的Mask R-CNN模型轻量级实现方案&#xff0c;面向深度学习初学者与PyTorch开发者&#xff0c;解决官方maskrcnn-benchmark因依赖C/CUDA原生扩展而无法在Windows环境下直接编译运行的核心痛点。方案通过纯Python逻辑重构关键…

2026/10/3 18:15:10 阅读更多 →
网络流量元数据留存系统hindsight:让事后复盘有据可查

网络流量元数据留存系统hindsight:让事后复盘有据可查

说实话&#xff0c;第一次看到“hindsight”这个词立项的时候&#xff0c;我第一反应是这项目名起得真妙。英文里 hindsight 本意是“事后聪明”&#xff0c;也就是事后诸葛亮。网络运维这行最不缺的就是事后聪明&#xff1a;每次故障复盘会&#xff0c;大家都能头头是道地指出…

2026/10/3 18:15:10 阅读更多 →
毕业论文降重与降AIGC全攻略:9款工具实测与完整操作流程

毕业论文降重与降AIGC全攻略:9款工具实测与完整操作流程

2026届毕业论文的压力&#xff0c;比往年多了一重。往年只要把重复率压下去就行&#xff0c;现在还得盯住AIGC检测率。我见过不少同学&#xff0c;知网查重过了&#xff0c;结果AIGC疑似比例标红一大片&#xff0c;学校要求限期整改&#xff0c;整个人直接懵了。更尴尬的是&…

2026/10/3 18:15:10 阅读更多 →
AI工程化实战:从零构建可交付、可维护的AI系统

AI工程化实战:从零构建可交付、可维护的AI系统

1. 这不是“搭积木”&#xff0c;而是亲手锻造AI系统的完整工程链 “AI Engineering from Scratch”——这个标题乍看像一句口号&#xff0c;实则是一道硬核考题。它不指代某个现成框架的快速上手&#xff0c;也不等于调几个API跑通demo&#xff1b;它直指一个被大量教程刻意绕…

2026/10/3 18:15:09 阅读更多 →
FMT飞控移植到RT-Thread的五个常见坑及排查方法

FMT飞控移植到RT-Thread的五个常见坑及排查方法

在嵌入式圈子里摸爬滚打这几年&#xff0c;我见过不少刚接触RTOS移植的朋友&#xff0c;一上来就想把FMT飞控系统整个搬到RT-Thread上跑起来。FMT作为一套代码比较完整的开源飞控&#xff0c;其内部自带多线程调度、uORB消息总线、传感器驱动、日志系统等模块&#xff0c;理论上…

2026/10/3 18:14:08 阅读更多 →

日新闻

把回忆蒸馏成 AI 的浪漫实验:为什么你需要前任.skill 完整指南

把回忆蒸馏成 AI 的浪漫实验:为什么你需要前任.skill 完整指南

把回忆蒸馏成 AI 的浪漫实验&#xff1a;为什么你需要前任.skill 完整指南 【免费下载链接】ex-skill 前任 skill 项目地址: https://gitcode.com/gh_mirrors/exsk/ex-skill 前任.skill 是一个运行在 Claude Code 上的开源 Skill&#xff1a;导入微信、iMessage、短信、…

2026/10/3 0:00:27 阅读更多 →
45个经典Linux面试题:从命令到网络排障的完整考点解析

45个经典Linux面试题:从命令到网络排障的完整考点解析

刚开始带应届生的时候&#xff0c;我最头疼的就是他们拿着一摞Linux面试题背得滚瓜烂熟&#xff0c;一上机全露馅。后来自己从被面的人变成面别人的人&#xff0c;才慢慢摸清楚&#xff1a;Linux面试题考的根本不是答案本身&#xff0c;而是你面对一个不确定的系统问题时&#…

2026/10/3 0:01:28 阅读更多 →
SAP生产预留实战指南:MB21/MB23/MB25协同与MRP集成

SAP生产预留实战指南:MB21/MB23/MB25协同与MRP集成

简介&#xff1a;本资源是一份面向SAP ABAP开发人员、生产计划专员及ERP实施顾问的实操型操作指南&#xff0c;聚焦SAP生产预留核心业务场景&#xff0c;系统解决物料预留创建、查询、校验与批量处理等高频问题。文档以结构化方式覆盖预留背景原理、OMC2编码规则、工厂级参数配…

2026/10/3 0:01:28 阅读更多 →

周新闻

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集&#xff1a;Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/10/3 9:14:33 阅读更多 →
SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/10/3 9:47:50 阅读更多 →
FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏 【免费下载链接】FireRed-OpenStoryline FireRed-OpenStoryline is an AI video editing agent that transforms manual editing into intention-driven directing through natural language …

2026/10/3 9:42:31 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 10:36:31 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/3 9:42:35 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/3 9:42:36 阅读更多 →