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

Bash中两种@扩展列表写法为何执行结果不一致?

两种Extglob写法在Bash脚本中的差异解析

问题场景

你编写的Bash脚本中,以下ls命令可正常列出./WORKS目录下指定后缀的文件:

#!/bin/bash

testor=$(shopt | grep extglob | awk '{ print $2 }' )

if [ "${testor}" = "off" ]
then
    shopt -s extglob
    shopt | grep extglob
fi

ls ./WORKS/@(*.sh|*.dat|*.txt)  

但将ls命令改为以下写法时,会出现No such file or directory错误:

ls @(./WORKS/*.sh|./WORKS/*.dat|./WORKS/*.txt)

核心差异原因

两种写法的本质是extglob模式的作用对象不同:

  • 第一种写法:./WORKS/@(*.sh|*.dat|*.txt)
    这里的@()仅作用于./WORKS/目录下的文件名。shell会先定位到./WORKS/目录,再用@(*.sh|*.dat|*.txt)匹配该目录下所有后缀为.sh、.dat或.txt的文件,最终把所有匹配到的文件路径合并成列表传给ls,完全符合extglob针对文件名匹配的设计逻辑。

  • 第二种写法:@(./WORKS/*.sh|./WORKS/*.dat|./WORKS/*.txt)
    这里的@()包裹的是完整路径模式,shell会按「或」逻辑依次处理每个分支:

    1. 先尝试扩展./WORKS/*.sh——如果目录下没有.sh文件,这个模式会保留字面量./WORKS/*.sh;
    2. 再依次处理另外两个分支,同样如果没有匹配文件就保留字面量。
      最终ls会收到这些未被正确扩展的字面路径,而系统中不存在名为./WORKS/*.sh的文件,因此报错。

    此外,extglob的@()是选择单个匹配的模式,而非合并所有分支的匹配结果。哪怕某个分支能匹配到文件,其他分支的未匹配字面量仍会被传递给ls,导致错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 22:40:37