简体   繁体   English

为什么git grep中的文件glob ** / *。cs无法显示所有* .cs命中?

[英]Why does the file glob **/*.cs in git grep not show me all *.cs hits?

So I wanted to find the use of NLog in my project, and I employed git grep to do so for me, but it found a few more cases than I needed: 所以我想在我的项目中找到NLog的用法,我使用git grep为我这样做,但是发现了比我需要的更多情况:

git grep NLog
GETA.Seo.Sitemap/Geta.SEO.Sitemaps.csproj:    <Reference Include="NLog, Version=2.1.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
GETA.Seo.Sitemap/Geta.SEO.Sitemaps.csproj:      <HintPath>..\packages\NLog.2.1.0\lib\net45\NLog.dll</HintPath>
GETA.Seo.Sitemap/Services/CloudinaryService.cs:                NLogger.Exception("Could not transform image", exception);
GETA.Seo.Sitemap/Services/CloudinaryService.cs:                NLogger.Warn("Url for cloudinary id was null");
GETA.Seo.Sitemap/Services/CloudinaryService.cs:                NLogger.Warn("Could not locate file object for cloudinary id in EpiServer");
 ....
 etc

Granted, it found what I was looking for, but I wanted to filter down to only the files ending in .cs . 当然,它找到了我想要的东西,但我只想过滤掉以.cs结尾的文件 So I tried doing this: 所以我尝试这样做:

git grep NLog **/*.cs
Web/Global.asax.cs:            NLogger.Info("Meny application start");

Just one hit, and neither of the two matches I had above were listed. 只是一击,我上面的两场比赛都没有列出。 I found this peculiar, and I probably have misunderstood the globbing matching of git grep. 我发现这很奇怪,而且我可能误解了git grep的全局匹配。 Could someone enlighten me? 有人可以启发我吗?

(Terminology note, for anyone reading this answer: expanding things like *.cs is called "globbing", 1 with *.cs being a "shell glob". A "shell" is your command line interpreter, which can be sh , bash , zsh , dash , tcsh , and so on. Git will has its own built-in globbing. The expanded characters are called wildcards , and they include * , ? , and [ . Some shells also treat { specially, which is an issue when using Git's reflog names like master@{yesterday} or stash@{2} . Quoting is always available for all of these.) (术语注释,对于任何阅读此答案的人:扩展*.cs类的东西称为“ globbing”,其中1*.cs为“ shell glob”。“ shell”是您的命令行解释器,可以是shbashzshdashtcsh ,并会等等。Git有它自己内置的通配符。扩展字符称为通配符 ,它们包括*? ,和[ 。一些炮弹也可治疗{特别,这是一个问题,当使用Git的引用日志名称(例如master@{yesterday}stash@{2}

The problem in this particular case—it may or may not happen to other people, depending on which shell they use and their circumstances—is that an unprotected (unquoted) * undergoes shell globbing. 在这种特殊情况下(取决于其他人使用或使用的外壳及其情况,其他人可能会或可能不会发生)的问题是,未受保护的(未引用) *会遇到外壳问题。 Some shells, such as bash, will, or at least can, expand ** the same way that Git does, meaning "recurse into subdirectories". 某些shell(例如bash)将(或至少可以)以与Git相同的方式扩展** ,这意味着“递归到子目录”。 Others can't, or depending on settings, won't. 其他人则不会,或者取决于设置。 2 2

If your shell expands **/*.cs to include the name Web/Global.asax.cs but not to include GETA.Seo.Sitemap/Services/CloudinaryService.cs (because that's down one more level of directory), then by the time Git gets the names, it's too late: the wildcard * characters are gone. 如果您的外壳程序将**/*.cs GETA.Seo.Sitemap/Services/CloudinaryService.cs扩展为包含名称Web/Global.asax.cs但不包含GETA.Seo.Sitemap/Services/CloudinaryService.cs (因为它位于目录的下一级), GETA.Seo.Sitemap/Services/CloudinaryService.cs当Git获得名称时,为时已晚:通配符*字符消失了。 Git never sees them and cannot do its own globbing. Git从来没有看到过它们,也无法做自己的globbing。

The simple solution is to protect the wildcard characters from shell globbing, by quoting them: 一种简单的解决方案是通过引用通配符来保护它们不受shell干扰:

git grep '**/*.cs'

(paired-up double quotes—as in git grep "**/*.cs" —also work in most shells, and prefix backslashes also work when used instead of quotes, as in git grep \\*\\*/\\*.cs : just protect each vulnerable character with a backslash). (成对的双引号-如git grep "**/*.cs" -在大多数shell中也适用,并且前缀反斜杠在代替引号时也适用,如git grep \\*\\*/\\*.cs :只需使用反斜杠保护每个易受攻击的角色)。 For many Git commands—it's not as important with git grep unless you're grepping older commits—it's a good idea to protect all wildcard characters at all times, so that they pass through to Git, because Git will expand them against something other than the current work-tree . 对于许多Git命令-除非您正在git grep较旧的提交,否则它与git grep并没有那么重要-始终保护所有通配符是一个好主意,这样它们就可以传递给Git,因为Git会将其扩展为针对除当前的工作树 The shell sees only the work-tree. 外壳程序仅看到工作树。 3 ) 3

Although it's shell-dependent, sometimes a wildcard character will match nothing and then be passed through. 尽管它取决于外壳,但有时通配符将不匹配任何内容 ,然后通过。 For instance, if you have no directory named sub and you write sub/* , some—not all—shells will pass the literal text sub/* to the command you ran. 例如,如果您没有名为sub目录并且编写了sub/* ,则某些(并非全部)shell将文字文本sub/*传递给您运行的命令。 4 In this case, if the command is a Git command, it can once again do its own globbing. 4在这种情况下,如果该命令是Git命令,它可以再次进行自己的globing。 It's not wise to depend on this, since as soon as there is something to match, the shell does the matching, instead of passing the original wildcard character on to the program. 这不是明智的做法,尽快依靠这个,因为因为一些东西来搭配,外壳做的,而不是通过原来的通配符上节目的匹配。


1 The name "glob" is shortened from "global", and in very early shells, was done by an external program named glob . 1名称“ glob”从“ global”缩写,在很早的Shell中,是由名为glob的外部程序完成的。 Early versions of Unix ran on machines with as little as 64 kilobytes of memory , so there was not a lot of room for fancy in-shell expansion. Unix的早期版本运行在只有64 KB内存的计算机上 ,因此花哨的shell内扩展空间不大。 See https://en.wikipedia.org/wiki/Glob_(programming) for more. 有关更多信息,请参见https://en.wikipedia.org/wiki/Glob_(编程)

2 In bash, Git-style expansion is controlled by setting the variable globstar . 2在bash中,通过设置变量globstar来控制Git样式的扩展。

3 This might even include the .git repository subdirectory itself, which is generally bad. 3这甚至可能包括.git存储库子目录本身,通常这很不好。 In bash, this is controlled by the variable dotglob . 在bash中,这由变量dotglob控制。

4 In bash, this is controlled by failglob . 4在bash中,这由failglob控制。

Note that bash provides nearly much every possible behavior of every possible shell. 注意,bash几乎提供了每个可能的shell的几乎所有可能的行为。 It's attempting to be a sort of universal shell. 它试图成为一种通用外壳。 Of course, this means it needs all these control variables too, which makes bash quite big. 当然,这意味着它也需要所有这些控制变量,这使得bash很大。 You would never be able to run it on a 64K non-split-I&D PDP-11. 您将永远无法在64K非拆分I&D PDP-11上运行它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM