如何用grep排除一些与某些扩展名不匹配的文件?

如何用grep排除一些与某些扩展名不匹配的文件?

我想OK从目录中递归输出包含该单词的所有行。但我需要从结果中排除一些扩展:

*~
*.map
*.js except *.debug.js

我试过:

grep -r --exclude={*~,*.map} "OK" /some/dir

除了我不知道如何从结果中删除所有这些非调试.js文件。

答案1

我只想通过一秒钟来grep删除它们:

grep -r --exclude={\*~,\*.map} "OK" bar/ | grep -vP '(?<!debug)\.js'

反转-v匹配,打印与模式不匹配的行,并-P启用 Perl 兼容正则表达式,让我们可以使用消极的回顾。这个特定的正则表达式将.js匹配不是前面的debug这意味着(因为我们正在反转匹配)只有那些.js文件才会被打印。

然而,正如 @QuestionOverflow 在评论中指出的那样,这可能会产生过滤掉的意想不到的副作用线包含OKjs因为grep -v应用于整个输出,而不仅仅是文件名。为了避免这种情况,只需添加一个冒号(这是grep用来分隔文件名和文件内容的):

grep -r --exclude={*~,*.map} "OK" bar/ | grep -vP '(?<!debug).js:'

如果您的输入行包含foo.js:或文件名包含:.因此,可以肯定的是,使用不同的方法:

grep -Tr --exclude={*~,*.map} "OK" bar/ | grep -vP '(?<!debug).js\t'

导致在文件名和文件内容之间打印制表符-Tgrep因此,如果我们只是将 a 添加\t到正则表达式的末尾,它将仅匹配文件名,而不匹配该行的内容。

仍然,使用find无论如何都可能更有意义。

答案2

我用来find定位文件并通过管道传输结果xargs

$ find . -type f \! -name "*~" \
                 \! -name "*.map" \
                 \! \( -name "*.js" -and \! -name "*.debug.js" \) \
         -print0 | xargs -0 grep "OK"

这会搜索每个文件不是匹配“ *~”、“ *.map”或“*.js但不匹配*.debug.js”。

使用find您可以轻松搜索相当复杂的规则,这种方法可以避免您意外删除 double 可能发生的误报grep

答案3

zsh你一起可以做到:

setopt extendedglob
grep OK some/dir/**/^(*~|*.map|(^*debug).js)

当然,前提是参数列表不太长,在这种情况下你总是可以这样做:

printf '%s\0' some/dir/**/^(*~|*.map|(^*debug).js) | xargs -0 grep OK

答案4

如果您不介意看到输出稍微乱序(如果您这样做,您可以对其进行排序):

grep -r --exclude={*~,*.map,*.js} "OK" /some/dir **/*.debug.js

这要求您的 shell 支持**递归通配符:zsh 是开箱即用的,bash 在您运行后执行shopt -s globstar,ksh93 在您运行后执行set -o globstar

如果没有**shell 的支持,您可以使用两个 grep 命令:

grep -r --exclude={*~,*.map,*.js} "OK" /some/dir
grep -r --include=*.debug.js "OK" /some/dir

相关内容