查找,grep和执行 - 一体化?

问题描述 投票:15回答:9

这是我用来在php文件中查找匹配(queryString)的命令,在当前目录中,使用grep,不区分大小写,并在行中显示匹配的结果:

find . -iname "*php" -exec grep -iH queryString {} \;

有没有办法将匹配的文件名管道到另一个脚本?

我可能会运行-exec命令两次,但这似乎效率低下。

我想在Mac OS X上做的事实上就是在发现者中“揭示”该文件。我想我可以处理那个部分。如果我不得不放弃内联匹配并让grep显示文件名,然后将其传递给第三个脚本,那也没关系 - 我会解决的。

但我实际上甚至不确定如何将输出(匹配的文件名)传递给其他地方......

救命! :)

Clarification

我想在finder窗口中显示每个文件 - 所以我可能不会使用-q标志并停在第一个。

我将在控制台中运行它,理想情况下我希望看到那里打印的内联匹配,以及能够将它们传递给另一个脚本,如oascript(applescript,在finder中显示它们)。这就是为什么我一直在使用-H - 因为我喜欢看到文件名和匹配。

如果我不得不满足于使用-l以便文件名可以更容易地通过管道传输到另一个脚本,那也没关系。但是我想看看@Charlie Martin下面的回复后,xargs可以在这里同时使用一个find和单个grep命令来帮助它们。

我确实说过bash,但我真的不介意,如果这需要像/bin/sh那样运行 - 我不太了解差异,但我知道有一些重要的。

谢谢大家的回复,我将在命令行尝试其中的一些,看看我是否能让他们中的任何一个工作,然后我想我可以选择最好的答案。如果您希望我澄清任何其他内容,请发表评论。

再次感谢!

shell grep find
9个回答
23
投票

你打赌。通常的事情是这样的

  $ find /path -name pattern -print | xargs command

所以你可能会这样做

  $ find . -name '*.[ch]' -print | xargs grep -H 'main' 

(测验:为什么-H?)

你可以继续这样做;例如。你可能会用

  $ find . -name '*.[ch]' -print | xargs grep -H 'main' | cut -d ':' -f 1

获取包含'main'的文件的文件名向量,或

  $ find . -name '*.[ch]' -print | xargs grep -H 'main' | cut -d ':' -f 1 |
      xargs growlnotify -

让每个名字成为Growl通知。

你也可以这样做

 $ grep pattern `find /path -name pattern`

要么

 $ grep pattern $(find /path -name pattern)

(在bash(1)中至少这些是等价的)但是你可以通过这种方式限制命令行的长度。

更新

回答你的问题:

(1)你可以在sh中做任何事情。我提到的有一点不同的是使用$(command)代替在命令周围使用反引号,并且在Mac上的sh版本中有效。 csh,zsh,ash和fish是不同的。

(2)我认为仅仅在$ open $(dirname arg)上会在包含目录上的opena finder窗口。


4
投票

-H替换为-l,您将获得与该模式匹配的文件名列表。


4
投票

听起来你想在Terminal.app会话中打开包含*.php的所有querystring文件。

你可以这样做:

find . -name '*.php' -exec grep -li 'querystring' {} \; | xargs open

通过我的设置,这将打开MacVim,每个文件都在一个单独的选项卡上。因人而异。


2
投票
find /home/aaronmcdaid/Code/ -name '*.cpp' -exec grep -q -iH boost {} \; -exec echo {} \;

我做的第一个更改是将-q添加到grep命令中。这是“如果发现任何匹配,则立即退出,状态为零”。

好消息是,当文件有许多匹配的行时,这会加速grep。你不在乎有多少场比赛。但这意味着我们需要另一个exec,以便在grep成功时实际打印文件名


2
投票

如果你有bash4,那就干嘛

grep pattern /path/**/*.php

**运营商就像

grep pattern `find -name \*.php -print`

1
投票

grep结果将被发送到stdout,因此另一个-exec谓词可能是最好的解决方案。


1
投票

管道到另一个脚本:

 find . -iname "*.php" | myScript

文件名将一次进入myScript 1行的标准输入。

您还可以使用xargs来形成/执行命令来对每个文件执行操作:

 find . -iname "*.php" | xargs ls -l

对你发现匹配的文件采取行动:

find . -iname "*.php" | xargs grep -l pattern | myScript

与模式不匹配的行为

find . -iname "*.php" | xargs grep -L pattern | myScript

0
投票

通常使用多个-execgrep -q将比管道更快,因为find暗示短路-a将每个并列的表达式分开,这些表达式没有用显式算子分隔。这里的主要问题是,如果grep匹配某些内容并且要打印匹配项,则需要执行某些操作。如果文件大小合理,那么这应该更快(因为grep -q在找到一个匹配后退出)

find . -iname "*php" -exec grep -iq queryString {} \; -exec grep -iH queryString {} \; -exec otherprogram {} \; 

如果文件特别大,则将其封装在shell脚本中可能比运行多个grep命令更快

find . -iname "*php" -exec bash -c \
  'out=$(grep -iH queryString "$1"); [[ -n $out ]] && echo "$out" && exit 0 || exit 1' \
bash {} \; -print 

另请注意,如果不特别需要匹配,那么

find . -iname "*php" -exec grep -iq queryString {} \; -exec otherprogram {} \;

几乎总是比管道解决方案更快

find . -iname "*php" -print0 | xargs -0 grep -iH | ...

此外,你应该在所有情况下都有-type f,除非你想要抓住*php目录


0
投票

关于哪个问题更快,你真的关心微小的时差,如果你想看看哪个会节省你的处理器一段时间,也许你可能会考虑使用命令作为“时间”的后缀“命令,看看哪一个表现更好。

© www.soinside.com 2019 - 2024. All rights reserved.