我想./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
'-print0
将NUL
终止其输出,而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')