正确使用 -R 查找点文件?

Alo*_*dal 6 command-line shell grep dot-files

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

me@here:~$ grep -IR .* -e culprit
Run Code Online (Sandbox Code Playgroud)

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

me@here:~$ grep -IR /home/me -e culprit
Run Code Online (Sandbox Code Playgroud)

结果证明这是一种非常愚蠢的行为,特别是如果我对mount我的$HOME. 太糟糕了,我无法找出快速、干净和正确的方法。(而且我的磁头正在慢慢磨损。)

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

Mik*_*kel 7

如果你在 Linux 上,你可以试试

grep -IR --exclude-dir=".." culprit .*
Run Code Online (Sandbox Code Playgroud)

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

grep -IR culprit .[!.]* ..[!.]*
Run Code Online (Sandbox Code Playgroud)

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

grep -IRs culprit .[!.]* ..[!.]*
Run Code Online (Sandbox Code Playgroud)

或者,如果没有以开头的文件,则使用bashandzsh nullglob选项使..[!.]*扩展为零..

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

grep -IR culprit .[!.]* ..[!.]*
Run Code Online (Sandbox Code Playgroud)

以上所有失败,总会有 find

find . -path "./.*" -exec grep culprit {} +
Run Code Online (Sandbox Code Playgroud)


jor*_*anm 5

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

shopt -s extglob
grep -IR 'foo' .!(|.)
Run Code Online (Sandbox Code Playgroud)

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


Alo*_*dal 4

感谢这个wiki,我发现有这个GLOBIGNORE变量:

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

$ echo .*
. .. .bash_history .bash_logout .bashrc .inputrc .vimrc
$ GLOBIGNORE=.:..
$ echo .*
.bash_history .bash_logout .bashrc .inputrc .vimrc
Run Code Online (Sandbox Code Playgroud)

好的一点是,这几乎没有副作用(我的意思是,您真正想要匹配..and 的频率是多少?),因此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:~$
Run Code Online (Sandbox Code Playgroud)