在Linux和Unix系统中,有两个常见的搜索命令:locatefind

每个优点和缺点是什么?当一个人比另一个人有好处?

评论

参见例如superuser.com/questions/199472/…

#1 楼

locate(1)相比,find(1)仅具有一大优势:速度。

find(1)locate(1)有许多优点:
find(1)是原始的,可追溯到AT&T Unix的第一个版本。您甚至可以通过Busybox在缩减的嵌入式Linux中找到它。这几乎是普遍的。

locate(1)find(1)小得多。 locate(1)的最早祖先是1983年才出现的,直到1994年被GNU findutils和4.4BSD所采用,才被广泛称为“ locate”。


locate(1)也是非标准的,因此默认情况下并未在所有位置安装它。某些POSIX类型的操作系统甚至没有提供它作为选项,并且在可用的情况下,实现可能缺少所需的功能,因为没有独立的标准来指定必须可用的最小功能集。

有一个事实上的标准,即BSD locate(1),但这仅是因为locate的另外两个主要版本实现了所有选项:-0-c-d-i-l-m-s-Smlocate实现了BSD locate中没有的6个附加选项:-b-e-P-q--regex-w。 GNU locate实现了这六个加另外四个:-A-D-E-p。 (我忽略了别名和诸如-?-h--help之类的微小差异。)

BSD和Mac OS X附带了BSD locate

大多数Linux都附带了GNU locate,但是Red Hat Linuxes和Arch则提供mlocate。 Debian既不在基本安装中也不安装,而是在其默认软件包存储库中提供了这两个版本。如果同时安装了两者,则“ locate”运行mlocate

从2014年12月发布的11.2开始,Oracle一直在Solaris中发布mlocate。在此之前,Solaris上默认未安装locate。 (大概是这样做是为了减少Solaris与Oracle Linux的命令不兼容,Oracle Linux基于Red Hat Enterprise Linux,后者也使用mlocate。)

IBM AIX仍未发行任何版本的locate ,至少从AIX 7.2开始,除非从用于Linux应用程序的AIX工具箱中安装GNU findutils

HP-UX在基本系统中似乎也缺少locate

较旧的“真实” Unix通常不包括locate的实现。

find(1)具有强大的表达式语法,具有许多功能,布尔运算符等。

find(1)可以选择文件不仅仅是名字。它可以通过以下方式选择:


年龄
大小
所有者
文件类型
时间戳
权限
深度之内子树...



按名称查找文件时,可以在所有版本的find(1)或GNU或BSD版本中使用正则表达式使用文件glob语法进行搜索。

当前版本的locate(1)接受glob模式,就像find一样,但是BSD locate根本不执行正则表达式。如果您像我一样,并且必须使用多种机器类型,那么您会发现自己更喜欢grep过滤,而不是依赖于-r--regex。 。


locate不一定搜索整个文件系统。您通常将其指向一个子目录,该子目录包含要对其进行操作的所有文件的父目录。 find实现的典型行为是弹出所有与您的模式匹配的文件,然后将其留给find(1)过滤,以将其喷出缩小到最小大小。系统上所有文件的列表!)

locate(1)的一些变体(例如grep)会根据用户权限限制输出,但这不是任何主要操作系统中locate /的默认版本。

locate(1)还能对找到的文件进行处理只是找到他们。最强大和得到广泛支持的此类运算符是slocate(1),但还有其他运算符。例如,在最新的GNU和BSD查找实现中,您具有locatefind(1)运算符。

-exec实时运行,因此其输出始终是最新的。

由于-delete依赖于过去几小时或几天内更新的数据库,因此其输出可能已过时。 (这是过时的缓存问题。)此硬币有两个方面:-execdir可以命名不再存在的文件。

GNU find(1)locate(1)具有locate标志,可以在打印出以前发现的每个文件的名称之前先检查文件是否存在,但这会消耗掉locate的一些速度优势,并且不是此外,在BSD mlocate中不可用。

-e将无法命名自上次数据库更新以来创建的文件。

您将了解到对locate输出的不信任,

有解决此问题的方法,但我不知道有任何广泛使用的实现方式。例如,存在locate,但它似乎不适用于任何现代Linux内核。


locate从来没有比运行它的用户更多的特权。

因为locate为系统上的所有用户提供了全局服务,所以它希望将rlocate进程作为find(1)运行,以便可以看到整个文件系统。这导致选择安全性问题:



以root用户身份运行locate,但使其输出文件世界可读,因此updatedb可以在没有特殊特权的情况下运行。这样可以有效地向所有用户公开系统中所有文件的名称。这可能足以引起实际问题。

在Mac OS X和FreeBSD上以这种方式配置了BSD root

将数据库写为仅可读updatedb,并将locate设为root,以便它可以读取数据库。这意味着locate实际上必须重新实现操作系统的权限系统,因此它不会显示您通常看不到的文件。它还会增加系统的攻击面,特别是冒着根升级攻击的风险。

创建一个特殊的“ root”用户或组以拥有数据库文件,并将该用户的locate二进制文件标记为setuid / group,以便它可以读取数据库。这并不能单独阻止特权升级攻击,但是可以极大地减轻一个人可能造成的破坏。

locate在Red Hat Enterprise Linux上是以这种方式配置的。

您仍然但是有一个问题,因为如果您可以在locate上使用调试器或导致其转储核心,则可以获取数据库的特权部分。


我没有办法创建真正的“安全” locate命令,而无需为系统上的每个用户分别运行它,这抵消了它与setuid/setgid相比的许多优势。


底线,两者都非常有用。当您仅尝试按名称查找特定文件(已知存在)时,mlocate会更好,但您只是不记得它的确切位置。 locate在需要重点检查的地方或需要其许多优点时会更好。

评论


抱歉,我忽略了“ slocate”段。 rlocate解决了过时的缓存问题。您可能要提到一些find的怪癖,例如find-“ $ dir”不健壮($ dir可能用作谓词),无法测试符号链接的属性,竞争条件问题...对我来说,找到并解决两个不同的问题。在很多地方,使用find都不切实际(例如,包含数百万个文件的目录)。查找是一个仅限于文件名的索引系统。

–StéphaneChazelas
13年1月4日在10:26

定位的第一个实现大致类似于find / -type f |。 gzip> locate.gz和zgrep“ $ 1”
– F. Hauri
2013年1月5日14:35



@ F.Hauri:有趣的琐事。还有更多信息:GNUlocate在findutils包中,其updatedb程序是根据find(1)实现的。因此,从这个意义上讲,locate(1)实际上需要find(1)。 :)

–沃伦·杨(Warren Young)
13年1月8日在21:45

@WarrenYoung为什么对foo(1)而不是foo进行常量引用? foo是否有其他不同的版本?

–关于坚果的坚果
13年3月15日在17:02



@nuttyaboutnatty:这是Unix手册中的一个古老约定,意味着手册第1节。确实,在其他节中没有find,locate等,因此不必为了消除歧义而使用相同的名称来消除歧义。本手册的各个部分(例如unlink(1)与unlink(2)),我们习惯于该约定的部分将其视为手册页参考。

–沃伦·杨(Warren Young)
13年3月15日在17:11

#2 楼

locate使用一个预先建立的数据库,该数据库应该定期更新,而find在文件系统上迭代以查找文件。

,因此,locatefind快得多,但是如果可以看到数据库,则可能不准确。因为缓存未更新(请参阅updatedb命令)。

find可以提供更多的粒度,因为您可以按文件的每个属性过滤文件,而locate使用与文件名匹配的模式。

#3 楼

如果没有仔细阅读手册页,Unix的新手或偶尔的用户无法成功使用find。从历史上看,某些版本的find甚至没有默认使用-print选项,这增加了用户的敌意性。

locate的灵活性较差,但在通常情况下使用起来更加直观。

评论


另一方面,locate必须维护一个数据库并定期运行,因此我已在驻留在我们专用网络上的所有Linux服务器上禁用了它。

– Rui F Ribeiro
2015年11月17日的12:00

这有什么难的?找 。 -name'nametosearch',或-iname(不区分大小写)。更换。带有用于搜索当前目录以外的目录路径的目录。在那里,即使不涉及文件问题,也可以满足新手用户需求的90%。 (我通常会使用find。-iname'* partialfilename *',如果我从/搜索,我会使用find / -maxdepth 5 -iname'* partialname *',这样可以减少搜索时间,同时查找我感兴趣的所有内容在90%的时间内。有75%的中级用户需求。

–通配符
2015年12月15日在20:21



#4 楼

定位的一个小缺点是它可能没有索引您感兴趣的文件系统的区域。在Debian桌面系统上,例如Linux Mint 17.2,/ etc / updatedb.conf文件配置为排除某些区域,包括/ tmp,/ var / spool和/home/.ecryptfs。

忽略/home/.ecryptfs可以防止加密目录中的文件名暴露给未经授权的用户。但是,如果您的主目录是使用ecryptfs加密的,则这也意味着您的主目录未建立索引,因此locate将在主目录中找不到任何内容。这可能会使它在很大程度上对您毫无用处(对我而言确实如此)。除了找不到结果之外,updatedb进程将定期加载磁盘而没有任何好处,如果您是系统的主要用户或唯一用户,则可能会被禁用。