You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

grep指定目录与glob通配符的写法差异解析

三条grep递归检索命令的差异

三个命令的核心差异来自Shell对传入路径的通配符展开规则,和grep自身的-r递归逻辑无关:

  • grep -rni . -e "keyword"
    直接将当前目录.作为检索起点传入grep,由grep自行控制全量递归遍历,会覆盖当前目录下所有文件、子目录(包括点开头的隐藏文件、隐藏目录,比如.git目录、.env文件),遍历效率最高,是递归检索的标准写法。

  • grep -rni * -e "keyword"
    命令执行前,Shell会先把*展开为当前目录下所有非隐藏的文件、子目录列表,再将展开后的路径列表传给grep,grep再对列表中的目录执行递归检索。这种写法默认不会匹配点开头的隐藏条目,你测试时发现和第一条结果数一致,只是因为当前目录下的隐藏条目没有命中关键词而已;两者结果顺序不同,是因为第一条按grep读取目录的原生顺序输出,第二条按Shell展开通配符时的文件名排序顺序输出。

  • grep -rni **/* -e "keyword"
    这里的**是Shell的扩展递归通配符(globstar),仅当手动开启对应Shell配置(bash下执行shopt -s globstar、zsh下执行setopt globstar)时才会生效,生效后**会递归匹配所有层级的子目录。你测试时该命令返回结果远多于前两条,核心原因不是特殊匹配规则,而是产生了大量重复遍历:

    Shell展开**/*时,会把所有层级的子目录、所有子文件都作为独立路径传给grep。grep拿到路径列表后,会对每一个传入的目录单独再做一次-r递归扫描。

    举个实际例子,假设存在路径./src/utils/str.js包含关键词,**/*展开后会把src、src/utils、src/utils/str.js三个路径都传给grep:

    1. 扫描src目录时,会递归命中src/utils/str.js一次
    2. 扫描src/utils目录时,会再次递归命中src/utils/str.js一次
    3. 直接扫描src/utils/str.js文件时,会第三次命中该文件
      路径深度越大,同一个文件被重复扫描的次数越多,最终输出的匹配结果自然远多于前两条命令。如果没有开启globstar,**的行为和普通*一致,此时**/*仅会匹配一级子目录下的内容,结果数反而会比前两条更少。

第三条命令的适用场景

日常检索几乎没有使用第三条命令的合理场景,这种写法既会产生大量重复扫描拖慢效率,还可能因为通配符展开规则的差异漏过文件。如果需要限定递归检索的路径范围,直接给grep传入明确的起点路径即可,不需要靠Shell展开多层通配符传参。

内容的提问来源于stack exchange,提问作者WalksB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 00:27:21