find 和 grep 管道不返回任何内容

find 和 grep 管道不返回任何内容

我有名为lect1.txtlect2.doc和 的文件lect3.doc

我想获取一个文件,该文件是一个.txt文件,并且包含lect作为文件名。

我试过

find *.txt | grep lect*

它什么也没返回。

但当我这样做的时候

find *.txt | grep "lect*"

它回来了lect1.txt

这两种表达方式有什么区别?

答案1

grep在命令行传递的文件中搜索第一个参数(模式)或者 stdin如果没有文件通过。

如果没有引号,您的 shell 将扩展lect*到目录中以lect.您的命令将是:

grep lect1.txt lect2.doc lect3.doc

意思是lect1.txt搜索两个.doc文件中的文本。除非其中一个文件中.doc包含该短语,否则它不会返回任何内容。lect1.txt更准确地说,它将查找lect1后跟任何字符(.) 后跟txt,因此它也会查找lect1-txtlect1xtxt

在第二个示例中,您引用了引号"lect.*",以便外壳程序不会扩展它,并将其按原样传递到grep.仅将模式作为参数传递,grep将搜索传入的文件名stdin以查找模式,我相信这就是您所追求的。

答案2

find *.txt | grep lect*

您通常希望提供路径名作为 的第一个参数find(1),而不是文件名。它当然不是文件名模式。 shell在调用之前会扩展为当前目录中*.txt所有文件的名称,这不是您想要的。*.txtfind

该命令更有用的变体是

find . -name 'lect*' | grep 'txt$'

或者

find . -name 'lect*txt'

另外,请注意find(1)使用全局表达式-name初选中,而grep(1)使用常用表达。这在这里很重要,因为这*在两个系统中意味着有些不同。

BSD 和 GNU 实现find具有非标准的-regex主要实现,它允许您使用正则表达式:

find . -regex '.*/lect.*txt'

请注意,该模式必须与所有的找到的路径find,这就是我们需要前缀的原因.*/,并且不需要像使用 一样将 固定txt到末尾。$grep

答案3

你误用了find,它意外地起作用了。你会看到 - 通过运行:

find *.txt 

你是什​​么实际上正在做的是调用:

find lect1.txt

而你所取得的成就只不过是echo。但是,如果您使用搜索条件运行 find - 例如:

find . -name '*.txt'

然后它将遍历当前目录.并打印任何子目录中与规范匹配的任何文件名。

但应该小心,因为 find 解释的 '*'、*shell 中的 和*正则正则表达式中的 含义不同。

如果您的greping*表示“前一个字符的零个或多个实例”。

所以你实际上是:

  • 回显所有文件名(globbing *.txt)。
  • grepping 打印任何与中间带有leclectlectt等的任何字符匹配的内容。lecttttttt

但在你的第一个例子中,你 grep 甚至没有走那么远 -正在扩展您的模式,因此它实际上正在查找任何匹配的内容echo lect*- 这可能会意外工作,因为您的目录中有一个文件可以适当扩展,但它没有执行您想要的操作。

我建议你想要的是:

find . -name 'lect*.txt' -print

相关内容