仅查找并回显找到模式的文件名

仅查找并回显找到模式的文件名

我经常使用这个,我试图实现的改进是避免回显在 grep 中不匹配的文件名。更好的方法来做到这一点?

    for file in `find . -name "*.py"`; do echo $file; grep something $file; done

答案1

find . -name '*.py' -exec grep something {} \; -print

会打印文件名匹配的线。

find . -name '*.py' -exec grep something /dev/null {} +

会在每个匹配行的前面打印文件名(我们添加的/dev/null情况是只有如果只传递一个文件来查找,则匹配文件 asgrep不会打印文件名。GNU 实现grep有一个-H选项作为替代方案)。

find . -name '*.py' -exec grep -l something {} +

将只打印至少有一个匹配行的文件的文件名。

打印文件名匹配的行,你可以使用 awk 代替:

find . -name '*.py' -exec awk '
  FNR == 1 {filename_printed = 0}
  /something/ {
    if (!filename_printed) {
      print FILENAME
      filename_printed = 1
    }
    print
  }' {} +

或者为每个文件调用grep两次 - 尽管效率较低,因为它会为每个文件运行至少一个grep命令,最多运行两个命令(并读取文件内容两次):

find . -name '*.py' -exec grep -l something {} \; \
                    -exec grep something {} \;

任何状况之下,find你不想像那样循环输出记得引用你的变量

如果您想通过 GNU 工具使用 shell 循环:

find . -name '*.py' -exec grep -l --null something {} + |
   xargs -r0 sh -c '
     for file do
       printf "%s\n" "$file"
       grep something < "$file"
     done' sh

(也适用于 FreeBSD 及其衍生产品)。

答案2

您可以告诉 grep 在输出中包含文件名。因此,如果有匹配,它将显示在控制台上;如果文件中没有匹配项,则不会为该文件打印任何行。

find . -name "*.py" | xargs grep -n -H something

来自man grep

-H       Always print filename headers with output lines
-n, --line-number
         Each output line is preceded by its relative line number in the file, starting at line 1.  The line number counter is reset for each file processed.
         This option is ignored if -c, -L, -l, or -q is specified.

如果您的文件名称中可能含有空格,则必须切换管道以使用 NUL 字符作为分隔符。完整的命令现在如下所示:

find . -name "*.py" -print0 | xargs -0 grep -n -H something

答案3

如果您使用 GNU grep,您可以使用它的-r--recursive选项来为您执行这个简单的查找:

grep -r --include '*.py' -le "$regexp" ./ # for filenames only
grep -r --include '*.py' -He "$regexp" ./ # for filenames on each match

find仅当您需要更高级的谓词时才需要。

答案4

使用-l论证。

for file in `find . -name "*.py"`; do grep -l something $file && grep something $file; done

更有趣的用法是:

for file in $(find . -name '*.py' -exec grep -l something '{}' +); do echo "$file"; grep something $file; done

相关内容