我正在尝试查找特定类型且不包含特定字符串的所有文件。我正在尝试通过管道 find 到 grep -v 来解决这个问题
例子:
find -type f -name '*.java' | xargs grep -v "something something"
这似乎不起作用。它似乎只是返回 find 命令找到的所有文件。我想做的基本上是找到与某个文件名匹配的所有 .java 文件(例如,以 SessionPb.java 中的“Pb”结尾)并且内部没有“extends SomethingSomething”。
我怀疑我做错了。那么该命令应该是什么样子呢?
答案1
这里没有必要xargs
。此外,您还需要使用grep
with-L
选项(不匹配的文件),否则它将输出文件内容而不是其名称,如您的示例中所示。
find . -type f -iname "*.java" -exec grep -L "something somethin" {} \+
答案2
你真的快明白了...
find . -type f -iname "*.java" -print0 | xargs -0 grep -v "something something"
点“.”说从这里开始。 (你的暗示它......但永远不要假设)。
-我的名字使用不区分大小写的搜索,以防万一(或只是在无情况下)。
-打印0将文件名发送到 xargs 并带有尾随 \x00 字符,这可以防止文件名中包含空格的问题。
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" *
会做更多的工作来搜索所有内容,但应该会给你一些输出。
答案3
计算机就是一台计算机:它正在做你告诉它做的事,而不是你想让它做的事。
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 不这样做,请让它不打印任何内容,并使用返回代码让调用 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'
如果您的 shell 是 ksh、bash 或 zsh,您可以让 shell 进行文件名匹配。在 bash 上,set -o globstar
首先运行(您可以将其放入您的~/.bashrc
)。
grep -L -E 'extends[[:space:]]+SomethingSomething' **/*.java
答案4
find -type f -name '*.java' 2>&1 | grep -v "something something"
您“grepping out”的内容显示到stderr,而不是stdout。
上面的命令将 stderr 重定向到 stdout