管道查找到grep -v


18

我正在尝试查找具有特定类型且不包含特定字符串的所有文件。我试图通过管道查找到grep -v来解决这个问题

例:

find -type f -name '*.java' | xargs grep -v "something something"

这似乎不起作用。似乎只是返回find命令找到的所有文件。我想做的基本上是找到所有与某个文件名匹配的.java文件(例如,在SessionPb.java中以'Pb'结尾),并且其中没有'extends SomethingSomething'。

我怀疑我做错了。那么该命令应该是什么样子呢?


您可能会添加使您认为它不起作用的原因。也许您的grep表达式太明确了?是否需要区分大小写的“ -i”?也可以在下面看到我的答案...
lornix

Answers:


21

这里没有必要xargs。另外,您还需要使用grepwith -L选项(不匹配的文件),因为否则它将输出文件内容而不是文件名,例如您的示例。

find . -type f -iname "*.java" -exec grep -L "something somethin" {} \+

1
-L已经进行了谈判,因为它意味着files _without_ match。因此,您-v在这里不需要选项。

3
末尾没有多余的+。
lynxlynxlynx 2012年

2
@ user946850每次我写信find -exec \+给我时,最好使用xargs。为什么没人在写评论之前看起来像男人?(:
2012年

5
@ user946850 -exec ... {} \+不等同于xargs。请阅读findutils文档!(我
James Youngman

2
@ user946850是的。区别之一是(默认情况下)xargs处理其输入并在空白处分隔参数。引号对也是特殊的(默认情况下)xargs。这些都不是真的-exec ... {} +。旧版本xargs曾经将下划线视为EOF指标,但现在情况不再如此。
James Youngman

7

真的,您几乎已经掌握了...

find . -type f -iname "*.java" -print0 | xargs -0 grep -v "something something"

点“。” 说从这里开始。(您的意思是它..但从不假设)。

-iname使用不区分大小写的搜索,以防万一(或不分大小写)。
-print0使用后缀\ x00字符将文件名发送到xargs,以防止文件名中包含空格的问题。

xargs上的“ -0”表示期望以\ x00结尾的文件名而不是返回值。

和你的grep命令...

差不多了。


编辑::

根据您的更新:

find . -type f -iname "*pb.java" -print0 | xargs -0 grep -iL "something"

应该有所帮助。(在@rush的回答中加上-L,干得好)

我的想法是您的grep需要'-i'选项,或者不太明确。

尝试按部分命令...这样输出的文件名看起来合适吗?

find . -type f -iname "*pb.java"

如果是这样,那么您的问题很可能是您的grep搜索模式不匹配(拼写错误?发生了!),或者根本没有匹配项。

绝对最坏的情况:

grep -riL "something" *

会在搜索所有内容上做很多工作,但是应该给您一些输出。


我尝试了您的修改,但仍没有得到预期的结果。我将尝试更新问题以使其更清楚。
Hyangelo 2012年

如果问题的作者只是想查找文件名,则grep不应为'grep -l -v'吗?
Bruce Ediger

他正在* .java文件中寻找特定的内容
lornix 2012年

xargs -0 grep -v "something something"xargs -0 grep -v "something something" /dev/null否则你将得到奇怪的结果时,发现不产生匹配的文件。
James Youngman

{咧嘴}是的,在那儿的某个地方,逻辑变得很毛茸茸。没有什么比反向错误逻辑多重测试更伤人头了。
lornix 2012年

4

计算机就是计算机:它在执行您要它执行的操作,而不是您想要执行的操作。

grep -v "something something"打印不包含的所有行something something。例如,它在以下三行中打印两行:

hello world
this is something something
something else

要打印不包含extends SomethingSomething任何位置的文件,请使用以下-L选项:

grep -L -E 'extends[[:space:]]+SomethingSomething' FILENAME…

某些版本的grep没有该-L选项(POSIX未指定)。如果不是,则不打印任何内容,并使用返回代码让调用Shell进行应做的事情。

grep -q -E 'extends[[:space:]]+SomethingSomething' FILENAME ||
echo "$FILENAME"

或者,使用awk。

awk '
    FNR == 1 && NR != 1 && !found { print fn }
    FNR == 1 { fn = FILENAME; found = 0; }
    /extends[[:space:]]+SomethingSomething/ { found = 1 }
    END { if (fn != "" && !found) print fn }
'

在Linux或Cygwin(或其他具有GNU grep的系统)上,您无需使用find,因为grep它可以递归。

grep -R --include='*.java' -L -E 'extends[[:space:]]+SomethingSomething'

如果您的外壳是ksh或bash或zsh,则可以使外壳执行文件名匹配。在bash上,set -o globstar先运行(您可以将其放入中~/.bashrc)。

grep -L -E 'extends[[:space:]]+SomethingSomething' **/*.java

哇,这更好。我正在使用'extends(/ s)+ SomethingSomething',据我所知,它似乎可以正常工作。此语法与扩展RegEx版本中指定的语法有什么区别?
Hyangelo

@Hyangelo \s是GNU grep扩展,我认为它是的同义词[[:space:]]
吉尔斯(Gillles)“所以-别再邪恶了”
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.