为什么命令“find | grep 'filename'”比“find 'filename'”慢这么多?

yoy*_*fun 10 command-line grep find search file-search

我尝试了这两个命令,命令 find | grep 'filename' 比简单find 'filename' 命令慢很多倍。

这种行为的正确解释是什么?

Kus*_*nda 11

(我在find这里假设是 GNU )

仅使用

find filename
Run Code Online (Sandbox Code Playgroud)

很快,因为它只会返回filename,或者filename如果它是目录,则返回里面的名称,如果当前目录中不存在该名称,则返回错误。这是一个非常快速的操作,类似于ls filename(但如果filename是目录则递归)。

相比之下,

find | grep filename
Run Code Online (Sandbox Code Playgroud)

将允许从当前目录和下面find生成所有名称的列表,grep然后进行过滤。这显然是一个慢得多的操作。

我假设实际上的意图是

find . -type f -name 'filename'
Run Code Online (Sandbox Code Playgroud)

这将filename在当前目录或下面的任何位置查找常规文件的名称。

这将与 一样快(或相当快)find | grep filename,但该grep解决方案将匹配filename每个找到的名称的完整路径,类似于-path '*filename*'使用find.


混淆来自对find工作原理的误解。

该实用程序采用多个路径并返回这些路径下的所有名称。

然后,您可以使用可能作用于文件名、路径、时间戳、文件大小、文件类型等的各种测试来限制返回的名称。

当你说

find a b c
Run Code Online (Sandbox Code Playgroud)

您要求find列出三个路径下的每个可用名称ab并且c. 如果这些恰好是当前目录中常规文件的名称,则将返回这些名称。如果它们中的任何一个恰好是目录的名称,那么它将与该目录中的所有其他名称一起返回。

当我做

find . -type f -name 'filename'
Run Code Online (Sandbox Code Playgroud)

这将生成当前目录 ( .) 及以下目录中所有名称的列表。然后它将名称限制为常规文件的名称,即不是目录等,使用-type f. 然后对匹配filename使用的名称有进一步的限制-name 'filename'。该字符串filename可能是文件名通配符模式,例如*.txt(请记住引用它!)。

例子:

以下似乎“找到”了.profile在我的主目录中调用的文件:

$ pwd
/home/kk
$ find .profile
.profile
Run Code Online (Sandbox Code Playgroud)

但实际上,它只是返回路径中的所有名称.profile(只有一个名称,就是这个文件的名称)。

然后我cd上一级并再试一次:

$ cd ..
$ pwd
/home
$ find .profile
find: .profile: No such file or directory
Run Code Online (Sandbox Code Playgroud)

find命令现在找不到任何名为.profile.

但是,如果我让它查看当前目录,然后将返回的名称限制为 only.profile,它也会从那里找到它:

$ pwd
/home
$ find . -name '.profile'
./kk/.profile
Run Code Online (Sandbox Code Playgroud)