Spotlight & MDFind

Indexing 服务

Maocx 系统的搜索服务 spotlight 想必大家都用过。它可以很便捷的帮我们找到想要的文件。

先举个例子,在 spotlight 中输入 _loadBlock, 我的电脑会出现以下结果:

loadBlock

spotlight 帮我找到了包含 _loadBlock 这个字符串的文件。

想象下,电脑硬盘中存储着如此多的文件,spotlight 是如何如此快速的查询到包涵这个字符串的文件的?

在查找答案之前,我们不妨自己来试着猜想一下,如果这个功能交给我们自己来做,我们会采用哪种技术方案来实现?
关于文件搜索,首先能想到的最简单的方法自然是遍历目录逐个文件对比,使用 find 的方式去查询。不过稍微想一下,如果使用这种方法在整个硬盘上找一个文件,得等多久才能找到一个文件。这肯定不是解决方案。那答案是什么?

我们不妨先把目光放到搜索这两个字上。提到搜索,首先想到的应该会是Google。而关于Google搜索引擎的工作原理,最简单的解释是:通过代码在全球收集信息,建立词组的索引数据库。Google处理用户的搜索请求,可以简单的理解成在索引数据库中查找结果的过程。
那 Macosx 的本地文件搜索会不会也是采取这种索引数据库的方式来实现的?答案是肯定的。Macosx 实现了自己的indexing的索引服务。那什么是indexing索引服务器,简单来讲: Macosx 系统会在平时建立磁盘上所有文件和目录的索引关系,维护出一个索引表,当要查找信息时直接从索引中查询即可。这个索引就好像是一本书的目录一样,我们根据自己要找的内容翻到对应的页面。

当然这当中还有很多复杂的处理过程,如当机器运行时,硬盘的文件产生变化,如何重新加载索引文件。更多的细节,我也没找出相关的文档来得到答案。先留个坑在这里吧。不过我们可以从其他开源的文件查询项目中了解一下业界对于这一块的处理方式。这里推荐 Lucene 给大家研究。(Lucene是一套用于全文检索和搜素的开源项目)。

mdfind

用 spotlight 的图形界面查询文件是很方便.但是我平常的工作过程中,常常需要知道文件的绝对路径,而图形界面并没有显示出来。关于如何在spotlight界面显示文件的详细路径,这里有个小 tips,具体操作是:选中某个搜索结果,长按 command 键,此时,界面右下方会出现文件的详细路径。不过如果文件路径太长,界面会显示不全,而且也有很好的没法去拷贝这个路径。

那如何解决文件路径显示不全,无法拷贝文件路径的问题呢?

Macosx 提供了终端执行命令mdfind,我们可以在 terminal 中使用mdfind来进行索引查询。比如要查询出文件内容中包含字符串 “_loadBlock”, 在ternimal中输入以下命令即可:

mdfind 'kMDItemTextContent="_loadBlock"' 

results:

/opt/dev/appstore_cracked/StoreKit_headers/SKStorePageViewController.h
/opt/dev/appstore_cracked/StoreKit_headers/SKStoreProductViewController.h
/opt/dev/iOS-Runtime-Headers/PrivateFrameworks/iTunesStoreUI.framework/SUWebViewController.h
/opt/dev/iOS-Runtime-Headers/PrivateFrameworks/iTunesStoreUI.framework/SUStorePageViewController.h
/opt/dev/iOS-Runtime-Headers/PrivateFrameworks/iTunesStoreUI.framework/SUPreviewOverlayViewController.h
/opt/dev/iOS-Runtime-Headers/PrivateFrameworks/Preferences.framework/PSLazyImagePromise.h
/opt/dev/iOS-Runtime-Headers/Frameworks/StoreKit.framework/SKStoreProductViewController.h
/opt/dev/iOS-Runtime-Headers/Frameworks/StoreKit.framework/SKStorePageViewController.h

对比终端查询结果和图一中的结果,会发现有两点出入:

  • (1) 图一中的 PrivateFrameworks, Frameworks 整个目录都没有被查出来。这里我猜测应该是Soptlight这个应用是对查询结果进行了筛选,把PrivateFrameworks, Frameworks目录下的文件从查询结果中剔除掉了。
  • (2) 图一中出现的nsBlocklistService.js,在terminal的查询结果中并没有出现。为了找出原因,我分别查看下”_loadBlock”在各个文件中的上下文,以下是节选

nsBlocklistService.js

this._loadBlocklist();

SKStorePageViewController

CDUnknownBlockType _loadBlock;

看上去问题应该是出在_loadBlock前后是否能跟别的字符串上,修改查询语句

mdfind 'kMDItemTextContent="_loadBlock*"' 

果然可以查询到结果

/Project/mozilla-central/toolkit/mozapps/extensions/nsBlocklistService.js

关于 mdfind 的一些常用查询语法,可参考 osxnotes,这里列举了大量的例子。