Windows 桌面顶部的全盘文件搜索 —— 自建 NTFS 索引引擎,毫秒级全盘搜索
Alt+N 全局唤起 · 平时收起为屏幕顶部中央的一枚吸顶把手 · 纯 Python + PySide6 + ctypes,零第三方引擎依赖
搜索窗口:查询「季度」—— 无边框深色卡片,路径惰性分批填充,右下角排序/时间筛选胶囊
吸顶把手:屏幕顶部居中的半透明蓝条(4× 放大),只在桌面露出时显示,点击即开
- 自建全盘索引引擎(零第三方引擎依赖,也不依赖 Windows 搜索服务):
直接解析 NTFS MFT 建索引,
USN Journal实时监听增/删/改名,毫秒级同步;缓存 mmap 映射,重启秒加载 - 丰富的查询语法:多词 AND、排除、词组、通配、OR、目录限定、正则、时间筛选(见查询语法)
- 顶部交互:失焦 /
Esc自动收起;吸顶把手被全屏窗口盖住时自动隐身、露出桌面再回来 - 结果操作:回车打开、
Ctrl+回车定位、右键菜单(打开 / 所在文件夹 / 在终端中打开 / 复制路径 / 复制文件名) - 排序与时间筛选:底栏胶囊一键切换 名称/最近修改 排序,全部/近一月/近一周 过滤
- 智能排除:回收站、系统还原点、
Windows\WinSxS组件库构建期直接不索引(省 30% 体量);支持exclude.txt自定义 - 开机自启:计划任务静默提权(登录即管理员,不弹 UAC;电池开机也生效)
- 中文友好:IME 组字上屏后才触发搜索(150ms 防抖),不干扰打字
方式一:直接使用 exe
dist\SnapFind.exe 单文件、自包含(无需安装 Python)。首次启动过一次 UAC(读 MFT 需要管理员权限),之后开机自启不再弹窗。
方式二:从源码运行
git clone <repo>
cd SnapFind
python -m venv .venv
.venv\Scripts\pip install PySide6
.venv\Scripts\python main.py非管理员运行时引擎不可用(界面会提示),完整功能请以管理员身份运行。
构建单文件 exe(自动同步图标、语法检查、结束旧实例、UPX 压缩):
build.bat :: 构建
build.bat run :: 构建并启动| 操作 | 方式 |
|---|---|
| 唤起 / 收起 | Alt+N(被占用时自动回落 Ctrl+Alt+N) |
| 打开 | 点击顶部吸顶把手 / 托盘图标左键 |
| 选择结果 | ↑ ↓,回车打开,Ctrl+回车 在资源管理器中定位 |
| 收起 | Esc 或点击其他窗口(失焦自动收起) |
空格分隔多个词 = AND;- 前缀 = 排除;引号 = 精确词组。
| 输入 | 含义 |
|---|---|
report |
名字含 report |
report 2026 |
同时含 report 与 2026(AND) |
png -icon |
含 png 且不含 icon |
"my file" |
精确含 my file 词组 |
*.png |
以 .png 结尾(大小写不敏感) |
read* / a*b |
通配:以 read 开头 / A*B 中间通配 |
*.png | *.jpg |
OR:任一匹配;负词全局生效 |
c:\windows\win |
只在 c:\windows(含子目录)内搜 win |
d:\img\*.png |
组合:D 盘 img 目录下的 png |
re:^read.*\.md$ |
正则匹配文件名(可带 d:\dir\ re:… 目录前缀;忽略大小写;写错报「无效正则」) |
report dm:today |
时间筛选:today / thisweek / thismonth / last7days / last30days / 2026-09-01 / 起..止;多个 dm: 取交集 |
纯目录输入(如
d:\)为目录浏览,暂不支持,返回空。
默认构建期直接不索引:卷根一级的 $recycle.bin、system volume information,以及 windows/winsxs(合计约 33 万行,占 C 盘 30%)——搜索零开销。扩展:%LOCALAPPDATA%\SnapFind\exclude.txt 每行一个目录名或 a/b/c 相对路径(# 注释;改动后需重建索引生效)。
实测环境:Windows 11 25H2,C 盘 106 万 + D 盘 25 万文件(排除后约 104 万条索引)。
| 指标 | 数值 |
|---|---|
| 普通子串查询 | 0.3–5 ms(多命中最坏 ~20 ms) |
后缀查询 *.png |
1–2 ms(高频后缀自 blob 尾部反向扫,凑满即停) |
| 正则全扫(75 万行) | 最坏 ~1 s |
| 首次建索引 | C: ≈ 34 s,D: ≈ 9 s(多卷并行时取最慢卷) |
| 重启加载缓存 | < 0.5 s(mmap 零拷贝) |
| 任务管理器内存读数 | ~10–20 MB(索引数据在文件映射里,不算私有内存;空闲自动裁剪) |
| 缓存文件 | ~68 MB / 磁盘(构建期压缩,无墓碑空洞) |
省内存的关键设计(对比"字符串列表"方案的 340MB+):
- 文件名不存 Python 字符串——UTF-8 拼接进 blob,每行 (start, len) 定位,搜索直接跑 C 速度的
find; - 行元数据全部定长数组(每行仅 25 字节),整个索引放在 mmap 文件映射里——映射页不属于进程私有内存,冷页由系统自动回收;
- USN 增量直接写映射页(append-only + 墓碑,掉电半写天然容错);路径缓存惰性 + 限量。
flowchart LR
UI["<b>UI 层</b><br/>search_window<br/>pill_window · tray"]
SVC["<b>门面</b><br/>search_service"]
ENG["<b>引擎层</b><br/>engine.py<br/>volume_index.py"]
SYS["<b>系统层</b><br/>winapi.py<br/>ctypes 唯一边界"]
UI --> SVC --> ENG --> SYS
- 引擎可扩展:新引擎(如 exFAT 目录扫描)实现
engine.py顶部注释里的协议即可接入,UI 无感知 - 日志:
%LOCALAPPDATA%\SnapFind\snapfind.log(含崩溃栈)
main.py 入口与装配:版本号、单实例、热键、引擎启动、托盘、把手
engine.py 引擎层唯一入口:FileResult(惰性 path) / 多卷状态机 + 并行搜索
volume_index.py 单卷索引核心:MFT 解析、查询语法、USN 实时应用、mmap 缓存(v14)
winapi.py ctypes 唯一边界:DLL 绑定、卷/驱动器查询、窗口枚举
hotkey.py 全局热键 + 单实例互斥体(隐藏消息窗口,线程内注册)
search_service.py 搜索门面:引擎状态 → 提示文案
search_window.py 搜索窗口(结果行惰性填充、右键菜单、排序/时间胶囊、失焦收起)
pill_window.py 吸顶把手(动态贴合顶部任务栏/屏幕边缘,被覆盖时隐身)
tray.py 托盘图标与深色圆角菜单(状态行 / 重建 / 自启 / 退出)
memtrim.py 空闲自动清理:路径/图标缓存 + 工作集裁剪
startup.py 开机自启(计划任务 XML 注册,电池开机可用)
file_icons.py SHGetFileInfo 图标提取(缓存)
app_icon.py 应用图标(内嵌 SVG,运行时多尺寸矢量渲染)
make_icon_assets.py 从 SVG 生成 assets/app_icon.ico
build.ps1/.bat 一键打包(图标同步 → 语法检查 → 结束旧实例 → PyInstaller + UPX)
docs/pitfalls.md 踩坑记录 26 条(NTFS/USN/mmap/PySide6 实战)
- 仅支持 NTFS 固定磁盘(exFAT/FAT32/网络盘不在索引范围)
- 需要管理员权限(读
\.\C:卷句柄) - 纯目录输入(
d:\)不支持目录浏览,返回空 - Win11 25H2 封锁了
FSCTL_ENUM_USN_DATA枚举,全量构建走逐 FRN 扫描(约 5s/80 万条)——这正是建索引要 30-40 秒的原因,详见踩坑 1 - 更多实现细节的坑见 docs/pitfalls.md(26 条实测踩坑)
见 CHANGELOG.md。
本项目以 MIT License 开源 —— 可自由使用、修改、二次分发,请保留版权声明。

