运行“grep”排除特定路径中的文件

运行“grep”排除特定路径中的文件

我想./test/main.cpp从搜索中排除该文件。

这是我所看到的:

$ grep -r pattern --exclude=./test/main.cpp
./test/main.cpp:pattern
./lib/main.cpp:pattern
./src/main.cpp:pattern

我知道可以通过在管道和过滤器排列中使用多个命令来获得我想要的输出,但是是否有一些引用/转义可以理解grep我本机想要的内容?

答案1

grep如果不同目录中有多个同名文件,则无法对某个目录中的文件执行此操作,请改用 find:

find . -type f \! -path './test/main.cpp' -exec grep pattern {} \+

答案2

我认为 GNU 不可能grep。不过你不需要管道。

find

find . ! -path ./test/main.cpp -type f -exec grep pattern {} +

zsh

grep pattern ./**/*~./test/main.cpp(.)

(排除隐藏文件,也排除 .git、.svn...)。

答案3

我可以写一本书:《失落的艺术xargs》。为每个文件启动find ... -exec … ';一个 grep (但 with 的变体-exec … +则不会)。好吧,我们现在正在浪费 CPU 周期,所以为什么不呢,对吧?但如果性能、内存和功耗是一个问题:使用 xargs:

find . -type f \! -path 'EXCLUDE-FILE' -print0 | xargs -r0 grep 'PATTERN'

GNU 的find'-print0NUL终止其输出,而xargs'-0选项将采用该格式作为输入。这可以确保您的文件具有任何有趣的字符,管道都不会感到困惑。该选项可确保在找不到任何内容的-r情况下不会出现错误。find

请注意,您现在可以执行以下操作:

find . -type f -print0 | grep -z -v "FILENAME EXCLUDE PATTERN" | 
  xargs -r0 grep 'PATTERN'

GNU grep 的-z作用与 xargs' 相同-0

答案4

作为记录,这是我更喜欢的方法:

grep pattern $(find . -type f ! -path './test/main.cpp')

通过将 保留grep在命令的开头,我认为这会更清晰一些——而且它不会禁用grep的颜色突出显示。从某种意义上说,find在命令替换中使用只是扩展/替换grep功能的(有限)文件搜索子集的一种方式。


对我来说,find -exec句法有点神秘。一种复杂性find -exec是(有时)需要转义各种字符(尤其是\;在 Bash 下使用时)。只是为了将事物放入熟悉的上下文中,以下两个命令基本上是等效的:

find . ! -path ./test/main.cpp -type f -exec grep pattern {} +
find . ! -path ./test/main.cpp -type f -print0 |xargs -0 grep pattern

如果你想排除子目录,可能需要使用通配符。我不完全理解这里的模式——谈论奥秘:

grep pattern $(find . -type f ! -path './test/main.cpp' ! -path './lib/*' )

进一步说明基于泛化find的解决方案用于脚本中grep命令行应包含-H/--with-filename选项。否则,在搜索结果中恰好只有一个文件名的情况下,它会改变输出格式find。这是值得注意的,因为如果使用 的grep本机文件搜索(使用该选项) ,则似乎没有必要-r

...不过,更好的是/dev/null作为第一个文件进行搜索。这解决了两个问题:

  • 它确保如果有一个文件要搜索,grep就会认为有两个并使用多文件输出模式。
  • 它确保如果没有要搜索的文件,grep将认为有一个文件并且不会挂在标准输入上等待。

所以最终的答案是:

grep pattern /dev/null $(find . -type f ! -path './test/main.cpp')

相关内容