定位与查找:彼此的用法、优缺点

m0n*_*awk 149 find search files locate

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

各自的优缺点是什么?当一个人比另一个人有好处时?

War*_*ung 187

locate(1)只有一个很大的优势find(1):速度。

find(1),虽然,有很多优点locate(1)

  • find(1)是原始的,可以追溯到 AT&T Unix 的第一个版本。您甚至可以通过 Busybox在精简的嵌入式 Linux 中找到它。这几乎是普遍的。

    locate(1)find(1). 最早的祖先locate(1) 直到 1983 年才出现locate直到 1994 年它才被广泛用作“ ”,当时它被GNU findutils4.4BSD 采用

  • locate(1)也是nonstandard,因此它不是默认安装在任何地方。一些 POSIX 类型的操作系统甚至不提供它作为选项,并且在它可用的情况下,实现可能缺少您想要的功能,因为没有独立的标准指定必须可用的最小功能集。

    有一个事实上的标准,即BSDlocate(1),但这只是因为其他两种主要风格locate实现了它的所有选项:-0, -c, -d, -i, -l, -m, -s, 和-Smlocate工具6个附加选项未在BSD locate-b-e-P-q--regex-wGNUlocate工具这六个加上又是4-A-D-E,和-p。(我忽略了别名和细微差别,例如-?vs -hvs --help。)

    BSD和 Mac OS X 提供 BSD locate

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

    Oracle2014 年 12 月发布11.2 以来一直mlocate在 Solaris中提供。在此之前,Solaris 上未默认安装。(据推测,这样做是为了减少 Solaris 与Oracle Linux的命令不兼容,后者基于 Red Hat Enterprise Linux,它也使用。)locatemlocate

    除非您从AIX Toolbox for Linux Applications安装 GNU,否则IBM AIX仍然不提供任何版本的locate至少从 AIX 7.2 开始findutils

    HP-UX显得缺乏locate基本系统。

    较旧的“真正的”Unixes通常不包括locate.

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

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

    • 年龄
    • 尺寸
    • 所有者
    • 文件类型
    • 时间戳
    • 权限
    • 子树中的深度...
  • 按名称查找文件时,您可以在 的所有版本中使用文件通配语法进行搜索find(1),或者在 GNU 或 BSD 版本中使用正则表达式进行搜索

    当前版本的locate(1)接受 glob 模式也是find如此,但 BSDlocate根本不做正则表达式。如果您像我一样必须使用各种机器类型,您会发现自己更喜欢grep过滤而不是开发对-r或的依赖--regex

    locate需要更强的过滤find,因为...

  • find(1)不一定搜索整个文件系统。您通常将它指向一个子目录,一个包含您希望它操作的所有文件的父目录。实现的典型行为locate(1)是喷出与您的模式匹配的所有文件,让其进行grep过滤,从而将其爆发缩小到大小。

    (邪恶提示:locate /可能会为您提供系统上所有文件的列表!)

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

  • find(1)可以对它找到的文件做一些事情,除了只是找到它们。最强大和最受支持的此类运算符是-exec,但还有其他运算符。例如,在最近的 GNU 和 BSD find 实现中,您有-deleteand-execdir运算符。

  • find(1) 实时运行,因此其输出始终是最新的。

    由于locate(1)依赖于过去数小时或数天更新的数据库,因此其输出可能会过时。(这是陈旧的缓存问题。)这枚硬币有两个方面:

    1. locate 可以命名不再存在的文件。

      GNUlocatemlocate-e标志使其在打印出它过去发现的每个文件的名称之前检查文件是否存在,但这会削弱一些locate速度优势,而且在 BSD 中不可用locate

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

    你学会了对locate输出有点不信任,知道它可能是错误的。

    有办法解决这个问题,但我不知道有任何广泛使用的实现。例如,有rlocate,但它似乎不适用于任何现代 Linux 内核。

  • find(1) 永远不会比运行它的用户拥有更多的特权。

    因为locate为系统上的所有用户提供全局服务,所以它希望其updatedb进程运行root时可以看到整个文件系统。这导致了安全问题的选择:

    1. updatedb以 root 身份运行,但使其输出文件世界可读,因此locate可以在没有特殊权限的情况下运行。这有效地向所有用户公开了系统中所有文件的名称。这可能足以导致真正的问题的安全漏洞。

      BSDlocate在 Mac OS X 和 FreeBSD 上以这种方式配置。

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

    3. 创建一个特殊的“ locate”用户或组来拥有数据库文件,并将locate二进制文件标记setuid/setgid为该用户/组,以便它可以读取数据库。这本身并不能阻止特权升级攻击,但它可以大大减轻可能造成的损害。

      mlocateRed Hat Enterprise Linux上以这种方式配置。

      但是,您仍然有问题,因为如果您可以使用调试器locate或使其转储核心,您就可以获得数据库的特权部分。

    我没有看到创建真正“安全”locate命令的方法,除了为系统上的每个用户单独运行它之外,这在很大程度上抵消了find(1).

归根结底,两者都非常有用。locate(1)当您只是尝试按名称查找特定文件时会更好,您知道该文件存在,但您只是不记得它的确切位置。find(1)当您有一个重点领域需要检查时,或者当您需要它的众多优势中的任何一个时,效果会更好。

  • @nuttyaboutnatty:这是 Unix 手册中的一个古老约定,意思是手册第 1 部分。虽然在其他部分确实没有 `find`、`locate` 等,因此不必在那里消除歧义手册不同部分中使用的名称(例如`unlink(1)` vs `unlink(2)`),我们这些习惯于约定的人将其视为手册页参考。 (4认同)
  • `locate` 的第一个实现大致类似于 `find / -type f | gzip > locate.gz` 和 `zgrep "$1" <locate.gz` (3认同)
  • @WarrenYoung 为什么有一个对 foo(1) 的常量引用而不仅仅是 foo ?foo 有不同的版本吗? (2认同)

小智 38

locate使用应定期更新的预建数据库,同时find遍历文件系统以定位文件。

因此,locate比 快得多find,但如果数据库 - 可以视为缓存 - 未更新(请参阅updatedb命令),则可能不准确。

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


Rus*_*ove 7

find如果不仔细阅读手册页,Unix 的新手或临时用户是不可能成功使用的。从历史上看,某些版本find甚至没有默认该-print选项,从而增加了用户的敌意。

locate 不太灵活,但在常见情况下使用起来更加直观。

  • 这有什么难的?`找到。-name 'nametosearch'` 或 `-iname` 不区分大小写。将 `.` 替换为要搜索的目录路径,而不是当前目录。在那里,这已经涵盖了新手用户的 90% 的需求,甚至无需进行文件通配。(我通常会使用 `find . -iname '*partialfilename*'`,如果我从 `/` 中搜索,我会使用 `find / -maxdepth 5 -iname '*partialname*'` 这会减少搜索时间,同时在 90% 的时间里找到我感兴趣的一切。那里,75% 的中级用户要求。):) (5认同)