众所周知,在Windows下,“指定打开某类型文件的默认程序”这件事情,是通过注册表来管理的。Unix/Linux下没有注册表(这一点我在文章的最后还要提到),那么在类Unix的桌面环境下,“文件类型 -> 打开该类型文件的应用程序”的映射关系是怎么实现的呢?以前我一直对此有疑问,今天我花了点时间做了个小小的研究,总结如下。
要明白这个问题,首先要明白三个概念。
1. MIME database
在Linux的桌面环境下都会有一个名为“MIME database”,这个database在本质上是一组xml文件,它的作用是定义系统已知的MIME文件类型,比如”text/plain”, “text/html”等等。系统级的”MIME database”文件存放于“/usr/share/mime/packages”目录,用户级的文件存放在“~/.local/share/mime/packages”目录。如果要在系统中修改或者添加MIME类型,可以参考这篇文章。另外,“gnomevfs-info”命令可以用来查看MIME类型的相关信息。
2. Desktop Entry Files
“Desktop Entry File”可以看作是指向系统中一个应用程序的快捷方式,比如“Ubuntu Main Menu”程序菜单中的各个菜单项,其实就是很多个的“Desktop Entry Files”(*.desktop文件)。每个“Desktop Entry File”至少会包含:名称,应用程序的完整路径,图标文件的完整路径等信息。更多的内容可以参考这里。
3. Registering Applications for MIME Types
这就是“文件类型 -> 打开该类型文件的应用程序”中的“->”。这个映射关系也是通过文件来表现的。从这里可以知道,这个文件的名称是“defaults.list”,系统级别的”defaults.list”的位置是“/usr/share/applications/defaults.list”,用户级别的”defaults.list”的位置是“~/.local/share/applications/defaults.list”。文件内容的具体格式如下:
1 | [Default Applications] |
相当直观,容易理解。
所以,如果要修改“打开某个类型文件的默认应用程序”,要做的是:
保证该MIME类型在“MIME database“是已经存在的,不存在则创建之(具体方法可以参考第一点中的链接文章);
保证要使用的应用程序有对应的“Desktop Entry File”,没有可以手工创建;
在系统级别或者用户级别的”defaults.list”文件中查找该”MIME”类型是否已经有对应的应用程序,如果没有则创建,有则修改为你想要使用的应用程序对应的“Desktop Entry File”名称。
所以可以想象,一些应用程序安装之后会将某些类型的文件会自动关联到该应用程序,这其实也是在安装程序中通过以上几个步骤实现的。
回头再来说说注册表。
在Unix的哲学中,有这样几点:
“Configuration data stored in text.” 以文本形式储存配置数据。
“Write programs that do one thing and do it well.” 写只做一件事、并且把它做好的程序。
“Write programs to handle text streams, because that is a universal interface.” 尽可能地让程序处理文本流,因为它是最通用的接口。
“Design for simplicity; add complexity only where you must.” 设计应该以简单为目标,只有在必须复杂的情况下增加复杂性。
容易看出,Windows下的注册表的概念和以上原则都有冲突:
首先它以自己特有二进制格式保存系统所有的配置信息,既不简单也不直接;
用户无法直接看到和编辑注册表里面的信息,必须通过特殊的工具和API方法;
复杂而臃肿,即使是经验丰富的程序员也未必能完全搞清楚里面数据的含义。
造成的结果是:本来为了提高用户体验和简化程序员工作的“注册表”,变成了用户和程序员共同的噩梦。
所以在我看来,“Windows注册表”这个例子很好地从反面证明了Unix哲学的意义。