使用 -R 正确地 grep 点文件?

使用 -R 正确地 grep 点文件?

有时我需要在未知的点文件中找到罪魁祸首,而不是试图找出应该归咎于哪个包(例如 xfce4 或 thunar?)以及它们的命名约定是什么(.app vs .application vs .some_old_name vs .config/app...),我只想采用快速而肮脏的方式:

me@here:~$ grep -IR .* -e culprit

但这种快速而肮脏的方式也是愚蠢的方式。几分钟后,我明白了这也.*意味着,我们就这样了。..有时我会求助于可能更慢且更肮脏的变体:

me@here:~$ grep -IR /home/me -e culprit

事实证明,这是一种极其愚蠢的行为,尤其是当我mount对自己有一些巨大或遥远的目标时$HOME。太糟糕了,我无法找出快速、干净和正确的方法。 (我的磁头正在慢慢磨损。)

是否有可能在通配符扩展中实现这一目标?即它的变体.*不匹配..(并且../........)?

答案1

如果你使用的是Linux,你可以尝试

grep -IR --exclude-dir=".." culprit .*

既然您询问了 shell 通配符,我的第一个想法是.[!.]* ..[!.]*,如

grep -IR culprit .[!.]* ..[!.]*

grep如果没有以 . 开头的文件,则会出现错误退出的问题..。为了解决这个问题,您可以添加-stogrep来告诉它忽略丢失的文件:

grep -IRs culprit .[!.]* ..[!.]*

或者,如果没有以以下开头的文件,请使用bashandzsh nullglob选项将其扩展为空..[!.]*..

shopt -s nullglob   # for bash
setopt nullglob     # for zsh

grep -IR culprit .[!.]* ..[!.]*

如果以上所有都失败,总会有find

find . -path "./.*" -exec grep culprit {} +

答案2

如果您有可用的 bash,则可以用来extglob仅获取点文件。

shopt -s extglob
grep -IR 'foo' .!(|.)

!扩展 glob 中的运算符是“not” 。此模式匹配以点开头的任何内容,不包括'.''..'

答案3

谢谢这个维基,我发现有这个GLOBIGNORE变量:

Bash 变量(不是 shopt)GLOBIGNORE 允许您指定 glob 不应匹配的模式。这可以让您解决臭名昭著的“我想匹配所有点文件,但不是 . 或 ..”问题:

$ echo .*
. .. .bash_history .bash_logout .bashrc .inputrc .vimrc
$ GLOBIGNORE=.:..
$ echo .*
.bash_history .bash_logout .bashrc .inputrc .vimrc

好的一点是,这几乎没有副作用(我的意思是,你有多少次真的来匹配..和?),因此from.甚至是可以接受的,并且对于手动任务,只需使用旧的glob,如 Q 中的第一个示例所示。export GLOBIGNORE=.:...bashrc.*

me@here:~$ set | grep GLOBIGNORE
GLOBIGNORE=.:.
me@here:~$ grep -IR .* -e culprit
.some-app/config: set culprit=1
me@here:~$

答案4

grep -IR culprit .[!.]*

.[!.]*匹配除以 . 开头的所有点文件..。由于点文件不以 开头..,所以没关系。

或者您可以使用 zsh,它从不包含...在 glob 中:

grep -IR culprit .*

更深奥的是,在 bash 中,如果您extglob打开了该选项 ( shopt -s extglob),则此选项有效,并且包含..?*(它也适用于 ksh 以及之后的 zsh 中setopt ksh_glob):

grep -IR culprit !(|.)

相关内容