命令在Shell中正常运行但在Bash脚本中报错的问题排查
问题:Bash脚本中无法使用扩展通配符匹配多后缀文件
问题场景
在交互式Bash环境中执行以下命令,能正常匹配指定后缀的文件:
$ ls files/@(*.text|*.txt|*.xt) files/f1.text files/f1.txt files/f1.xt
但将命令写入Bash脚本后执行,却抛出文件不存在的错误。脚本内容如下:
#!/bin/bash ls files # 此命令可正常执行 ls files/@\(*.text\|*.txt\|*.xt\) # 此命令执行失败
执行脚本后的输出:
$ ./testScript.sh files/f1.text files/f1.txt files/f1.xt ls: cannot access files/@(*.text|*.txt|*.xt): No such file or directory
尝试多种写法均未解决:
- 直接写
ls files/@(*.text|*.txt|*.xt):报语法错误line 4: syntax error near unexpected token '(' - 转义写法
ls files/@\(*.text|*.txt|*.xt\):报line 4: *.xt): command not found - 用
sh ./testScript.sh执行:报错与原问题一致 - 使用绝对路径
/files/@(*.text|*.txt|*.xt):仍报错
已确认当前默认Shell为Bash:
$ echo $SHELL /bin/bash
原因分析
@(...)属于Bash的扩展通配符(extglob)特性,该特性默认在交互式Shell中开启,但在**非交互式Shell(即脚本运行环境)**中默认关闭。因此脚本中直接使用该语法时,Bash会将@(*.text|*.txt|*.xt)当作普通字符串处理,导致ls无法找到对应文件。此外,若用sh执行脚本,由于sh本身不支持extglob特性,同样会报错。
解决方案
方法1:在脚本中开启extglob特性
在脚本开头添加shopt -s extglob命令,开启扩展通配符支持,之后直接使用原命令即可,无需转义:
#!/bin/bash shopt -s extglob ls files ls files/@(*.text|*.txt|*.xt)
方法2:使用其他替代匹配方式
如果不想依赖extglob特性,可改用以下方式实现相同效果:
- 多个通配符直接组合:
ls files/*.text files/*.txt files/*.xt - 使用find命令(适合更复杂的匹配场景):
find files -maxdepth 1 -type f \( -name "*.text" -o -name "*.txt" -o -name "*.xt" \)
内容的提问来源于stack exchange,提问作者Ammar Hussein
相关产品推荐
相关产品推荐

