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

如何从sh向bash脚本传递ext glob并实现正确展开?

如何在Bash脚本中正确处理传递的大括号扩展/Extglob模式

问题原因

你遇到的问题核心在于:

  • 当用引号包裹"{a,1}*.txt"传递时,当前Shell不会执行大括号扩展(这是Bash的参数扩展特性,不属于glob匹配);脚本中变量展开后,Bash也不会回溯处理这个字符串的大括号扩展,只会把它当作一个字面文件名模式去匹配,自然找不到目标文件。
  • 脚本里开启了extglob但实际用的是大括号语法,两者是不同的Bash特性:extglob的语法是@(a|1)*.txt这类,而{a,1}*.txt属于大括号扩展。

解决方案

方案1:不使用引号传递参数(简单直接)

如果参数中没有空格或特殊字符,直接让当前Shell先完成大括号扩展,再把结果传给脚本:

./se.sh {a,1}*.txt

同时修改脚本,让它处理所有传入的参数(而不是仅第一个):

#!/bin/bash

shopt -s nullglob
# 若使用extglob语法则开启,大括号扩展不需要
# shopt -s extglob

# 遍历所有传入的参数对应的文件
for f in a/path/to/all/files/"$@"; do
  echo "file process: ${f}"
done

shopt -u nullglob
# shopt -u extglob

方案2:脚本内用eval解析带扩展的参数(适合必须用引号传递的场景)

如果必须用引号包裹参数(比如参数包含空格、特殊符号),可以用eval强制Bash重新解析变量内容,完成大括号扩展和glob匹配:

#!/bin/bash

pattern="$1"

shopt -s nullglob
shopt -s extglob  # 若用extglob语法则开启,大括号扩展可省略

# 用eval将模式与路径拼接后解析,结果存入数组
eval "target_files=(a/path/to/all/files/${pattern})"

for f in "${target_files[@]}"; do
  echo "file process: ${f}"
done

shopt -u nullglob
shopt -u extglob

执行命令:

./se.sh "{a,1}*.txt"
# 若用extglob语法则执行:./se.sh "@(a|1)*.txt"

注意:eval会执行字符串中的任意Shell命令,仅在参数来源可信时使用。

补充:区分大括号扩展与Extglob

  • 大括号扩展:{a,1}*.txt → 先扩展为a*.txt和1*.txt,再做glob匹配
  • Extglob:@(a|1)*.txt → 直接作为单个glob模式匹配以a或1开头的txt文件,需要开启shopt -s extglob

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 07:20:17