find -exec grep {} \; egrep -v string \; # 命令链刹车

find -exec grep {} \; egrep -v string \; # 命令链刹车

我正在使用 find 命令来查看它的行为,但我有点迷失。

第一位很好:

find . -maxdepth 1 -exec grep -l abc {} \;
grep: .: Is a directory
./file2.pdf
./file1

然后我尝试通过链接另一个 egrep 命令来排除 .pdf 文件,但失败了。

find . -maxdepth 1 -exec grep -l abc {} \; -exec egrep -vl '*.pdf' {} \;
grep: .: Is a directory
./file2.pdf
./file2.pdf
./file1
./file1

为什么它不排除 .pdf 文件并且还打印两次结果?

答案1

egrep -vl '*.pdf' some_file检查文件内容,不是名字。

排除名称的正确方法find是否定(!)适当的-name(或-iname如果可用)表达式。例如:

find . -maxdepth 1 ! -name '*.pdf' -exec grep -l abc {} \;

每个结果都打印两次,因为在第一次grep打印并返回成功之后,第二次(egrep)显然没有*.pdf在相应的文件内容中找到(解释为扩展正则表达式),因此(注意-v)打印了相同的名称。

注意-exec,这也是一个测试。在你的情况下,如果第一个-exec报告失败,则第二个-exec将不会被触发。-exec如果第一个报告grep失败,它将报告失败。grep如果在文件中找不到模式,它将报告失败。这意味着第一个未打印的任何文件都grep无法由第二个打印(egrep),因为第二个甚至不会为该文件运行。


排除.pdf文件的另一种方法是过滤输出你的第一个find(在你的情况下实际上是greps 的输出;你find本身没有打印任何内容)。像这样:

find . -maxdepth 1 -exec grep -l abc {} \; | grep -iv '\.pdf$'

但是如果由 返回的任何路径find是多行的(即如果它包含换行符;Linux 中的文件名可以),则添加的grep将无论如何分别感知每一行,就好像这些行引用了多个文件一样;并且您将得到意想不到的结果。因此在find( -name …) 内进行测试更好。

相关内容