Bash中执行$1*$2为何会列出当前目录所有文件与文件夹
现象成因
这个结果是Bash默认的两层展开规则先后执行导致的,属于符合设计预期的行为:
- 第一层是参数展开:你执行脚本时没有传入任何位置参数,直接在终端执行命令时
$1、$2既不是已定义的普通变量,也不是有赋值的位置参数,在Bash默认配置(未开启set -u未定义变量报错)下,未绑定值的变量展开结果为空字符串。这一步执行完后,$1*$2会被处理成单独的*字符。 - 第二层是文件名通配展开(glob展开):未被引号包裹的
*是Bash的通配符,默认规则下可以匹配任意长度的任意字符(包含空字符)。当通配符没有和其他固定字符组合时,会匹配当前工作目录下所有不以.开头的文件、文件夹,最终把匹配到的名称按字典序排列,作为参数传给echo命令。
你看到的目录列表输出,本质上和直接执行echo *的效果完全一致。
官方规则依据
Bash官方手册明确记录了这两个机制:
- 参数展开规则:默认场景下,未设置、未赋值的参数/位置参数展开结果为空;只有开启
set -u(即nounset选项)时,引用未绑定的变量才会触发报错。 - 文件名展开规则:未被单/双引号包裹的通配符会触发文件名匹配,
*作为通配符可匹配任意字符串;如果通配符没有匹配到任何文件,默认配置下会保留通配符原字符输出,若开启nullglob选项则展开为空,开启failglob选项则直接抛出匹配错误。
快速验证方法
你可以通过几个简单命令验证这个逻辑:
- 给表达式加双引号阻止通配展开:执行
echo "$1*$2",因为引号内的*不会被识别为通配符,输出结果为* - 开启未定义变量报错:执行
set -u后再跑echo $1*$2,Bash会直接抛出$1: unbound variable的错误,不会输出目录列表 - 传入位置参数改变展开结果:执行
bash script.sh doc "",参数展开后得到doc*,最终只会列出当前目录下所有以doc开头的文件和文件夹
内容的提问来源于stack exchange,提问作者Nicholas Dunlop
相关产品推荐
相关产品推荐

