有时我需要在未知的点文件中找到罪魁祸首,而不是试图找出应该归咎于哪个包(例如 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
如果没有以 . 开头的文件,则会出现错误退出的问题..
。为了解决这个问题,您可以添加-s
togrep
来告诉它忽略丢失的文件:
grep -IRs culprit .[!.]* ..[!.]*
或者,如果没有以以下开头的文件,请使用bash
andzsh
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 !(|.)