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

Makefile中Bash通配符失效问题排查与解决

问题分析与解决方案

咱们先拆解下你遇到的问题:为啥make working能正常输出gotcha,但make error却没触发echo?核心问题出在bash通配符扩展和test命令(也就是[ ])的行为上,再加上你Makefile里设置的SHELL := /bin/bash -f推波助澜。

为什么working正常而error失效?

先看working目标的代码:

if [ -d ffprob_runfail ]; then echo "gotcha" ;fi

这里ffprob_runfail是明确存在的目录,[ -d ]作为一元运算符,直接检查这个具体路径是否为目录,逻辑完全没问题,所以test命令返回true,echo执行。

再看error目标的问题:

if [ -d ffprob_* ]; then echo "gotcha" ;fi

这里的坑有两个:

  1. 通配符扩展的不确定性:bash会先尝试把ffprob_*扩展成所有匹配的目录/文件。如果匹配到多个条目,[ -d ]就会收到多个参数(比如[ -d ffprob_runfail ffprob_other ]),但-d是一元运算符,只接受一个参数,这时候test命令会因为参数格式错误直接返回false,echo自然不执行;如果只匹配到一个目录,这时候扩展后和working的逻辑一样,能正常执行,但这只是巧合;如果没有匹配到任何条目,ffprob_*会保留字面量,test就会检查名为ffprob_*的目录是否存在,显然不存在,也不会触发echo。
  2. -f选项的影响:你设置了SHELL := /bin/bash -f,-f选项会直接禁用bash的通配符扩展,不管有没有匹配的目录,ffprob_*都会被当作字面量处理,test检查的是名为ffprob_*的目录,自然不存在,所以echo不会执行——这也是你转义*没用的原因,转义后同样是字面量,不会被扩展。

另外补充个关键点:bash的-d运算符确实不能直接结合通配符使用,它只针对单个路径做判断,没法批量检查。

正确的实现方式

你自己给出的right目标就是正确的思路:通过循环遍历所有匹配ffprob_*的条目,逐个检查是否为目录。代码再贴一遍:

right :
	for item in ffprob_* ; do if [ -d "$$item" ] ; \
	then echo "gotcha $$item";fi;done

这里要注意两个细节:

  • 使用$$item而不是$item:因为Makefile会把单个$解析成变量引用,所以要加一个$转义,让bash能拿到循环变量。
  • 给$$item加引号:如果目录名里有空格(虽然你这里没有),引号能避免bash把空格当成参数分隔符,保证路径被正确识别。

执行这个目标时,bash会先扩展ffprob_*成所有匹配的条目,然后逐个检查每个条目是否为目录,只要有一个符合条件,就会输出对应的gotcha信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 03:56:16