与图形文件搜索实用程序相比,为什么GNU这么快找到?


47

我正在尝试查找主目录和所有子目录中不存在的文件。

find ~/ -name "bogus"几秒钟后就给我提供了该信息,但是KDE的dolphin文件管理器需要近3分钟来完成相同的操作。这与我以前在GNOMEbeagle上的经验相对应。

如何find能做到同样的速度非常快,而图形搜索(这是更直观的比命令行参数的使用)蛞蝓背后?


我不知道“海豚”是什么,但是它也可以文件内部查看吗?
库萨兰达

1
它是KDE的图形文件管理器:kde.org/applications/system/dolphin它具有搜索内部文件的功能,但是在此简短测试中并未启用该选项。
红色

9
您在海豚中搜索过一次以上吗?可能是第一次“索引”。而且“查找”也很慢。如果文件早于上次对定位数据库进行索引的时间,请尝试“定位” ;-)
Rinzwind

我使用的locate频率高于find,在一个巨大的文件夹中使用速度更快
phuclv

11
虽然locate确实很适合查找文件,但这有点麻烦,因为它使用了完全不同的方法:findGUI工具(如GUI)Dolphin按需遍历文件树,而locate使用先前创建的索引结构。
迈克尔·谢弗斯

Answers:


68

特别是使用Baloo查看Dolphin,即使您正在执行简单的文件名搜索,它似乎也在其搜索域中查找每个文件的元数据。当我跟踪该file.so过程时,我看到了对的调用lstatgetxattrgetxattr再次对每个文件甚至..条目进行了调用。这些系统调用检索有关文件的元数据,该元数据与文件名存储在不同的位置(文件名存储在目录内容中,但元数据在inode中)。多次查询文件的元数据是便宜的,因为数据将存储在磁盘缓存中,但是查询元数据和不查询元数据之间可能会有很大的不同。

find更聪明。它试图避免不必要的系统调用。它不会调用,getxattr因为它不会基于扩展属性进行搜索。当遍历目录时,它可能需要调用lstat不匹配的文件名,因为它可能是要递归搜索的子目录(lstat是系统调用,它返回文件元数据,包括文件类型,例如常规/目录/符号链接/…)。但是find有一个优化:它从链接数中知道一个目录有多少个子目录,并且lstat一旦知道遍历所有子目录就停止调用。特别是在叶目录(没有子目录的目录)中,find仅检查名称,不检查元数据。此外,某些文件系统在目录条目中保留文件类型的副本,因此,如果这是唯一需要的信息,find则甚至不需要调用lstat它。

如果find使用需要检查元数据的选项运行,它将进行更多lstat调用,但是lstat如果不需要信息,它仍然不会对文件进行调用(例如,由于先前条件排除了文件,匹配名称)。

我怀疑其他重新发明find轮子的GUI搜索工具比经过数十年优化的命令行实用程序同样不那么聪明。至少,如果您“无处不在”搜索,Dolphin至少足够聪明,可以使用定位数据库(其限制在UI中尚不明确,结果可能已过时)。


22
GNU find非常“聪明”,以致于它错过了某些文件系统类型上的某些文件。GNU发现中的一个众所周知的错误是,它错误地假设目录的链接数为。2 + number of sub-directories.这适用于实现UNIX V7文件系统中的设计错误的文件系统,但不适用于所有文件系统,因为这不是POSIX要求。如果您想获得GNU make的有用性能数字,则需要指定-noleafon,以告知GNU make正确运行。
凌晨

12
@ schily,GNU find可能早已存在该错误,但是我怀疑您会发现现在需要-noleaf手动指定的情况。至少在Linux上getdents()(和readdir()),AFAICT会告诉哪些文件是UDF,ISO-9660,btrfs上的目录文件,它们没有实数...条目,并且find在那儿表现正常。您是否知道GNU find出现问题的一种情况?
斯特凡·Chazelas,

4
只需使用来自debian的烂genisoimage来使用“嫁接点”创建Rock Ridge文件系统,目录中的链接数是一个随机值。由于Rock Ridge实现了链接计数和。/ ..,因此GNU find通常不会在这样的文件系统上找到所有文件。
凌晨

4
@StéphaneChazelas:上次我检查(针对我的硕士学位论文)时,通过断言确切地说2意味着已知的叶子而不是<= 2来修复了该错误。未实现2+计数器的文件系统都针对目录链接计数返回1。一切都很好。现在,如果某天某人制作了一个文件系统,该文件系统对不具有此属性的目录进行了硬链接,那么某人的日子将会很糟糕。
约书亚

15
@schily,我无法在Debian 上获得带有嫁接点的随机链接计数和genisoimage 1.1.11的RR,即使我对iso图像进行二进制编辑以将链接计数更改为随机值,我仍然看不到任何GNU问题find。并且无论如何,strace -v表明可以getdents()正确返回目录的d_type = DT_DIR,因此GNU find不必使用链接计数技巧。
斯特凡·Chazelas,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.