如何在sh调用bash脚本时控制glob展开,传递glob并在bash中展开
解决方案
方法1:修改wrapper脚本为命令字符串解析模式
把你的wrapper.sh改成这样:
#!/usr/bin/env bash # 开启所需的bash glob特性 shopt -s globstar extglob # 把传入的所有参数拼接成命令字符串,由bash解析执行 eval "$*"
然后在sh环境中这样调用:
wrapper.sh 'echo **/*.@(yml|yaml)'
为什么这个能行?
- 单引号包裹的命令字符串会原封不动传递给wrapper里的bash,sh不会提前解析
@(yml|yaml)这个extglob语法; - bash开启
extglob和globstar后,eval会重新解析整个命令字符串,此时glob规则会被正常展开,再执行echo输出结果。
方法2:无需wrapper,直接用嵌套bash -c + eval
如果不想改wrapper,也可以直接在sh里执行:
bash -c 'shopt -s globstar extglob; eval "echo **/*.@(yml|yaml)"'
解决原命令报错的原因
之前你执行bash -c 'shopt -s extglob; echo **/*.@(yml|yaml)'报错,是因为bash在解析整个命令行的时候,会先处理语法结构,这时候extglob还没被开启,所以@(...)会被当成无效语法抛出错误。而eval会在shopt之后执行,此时extglob已经开启,就能正常解析glob规则。
为什么之前的wrapper调用失败?
wrapper.sh 'echo **/*.@(yml|yaml)':"$@"会把整个字符串当作一个单独的命令,bash会去找名为echo **/*.@(yml|yaml)的可执行文件,自然找不到;wrapper.sh echo '**/*.@(yml|yaml)':引号包裹的**/*.@(yml|yaml)是字面量参数,echo直接输出,不会触发glob展开;wrapper.sh echo **/*.@(yml|yaml):sh会先尝试解析@(yml|yaml),但sh不支持extglob语法,直接报语法错误。
内容的提问来源于stack exchange,提问作者Anentropic
相关产品推荐
相关产品推荐

