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

如何在Bash数组中正确使用星号(*)并实现带通配符的命令执行

如何在Bash数组中正确使用星号(*)并实现带通配符的命令执行

这个问题我之前踩过一模一样的坑!核心原因是Bash处理通配符的时机和引号的作用冲突了~

你原来的写法失败,是因为给/tmp/hello/*套了双引号,Bash会把星号*当成一个普通的字符,而不是通配符来解析。所以数组里存的就是字面意义上的/tmp/hello/*,执行的时候cp会去寻找名字正好是*的文件,自然找不到就报错了。

下面给你几种正确的实现方式,你可以根据自己的使用场景来选:

方法1:直接裸写通配符(最适合固定路径场景)

如果你的通配符路径是固定的,不需要动态生成,那赋值给数组的时候千万不要加引号,让Bash在赋值阶段就自动展开通配符:

mkdir -p /tmp/hello
echo "hello" > /tmp/hello/hello.txt
echo "world" > /tmp/hello/world.txt
mkdir -p /tmp/world

declare -a my_array=()
my_array[0]="cp"
my_array[1]=/tmp/hello/*  # 这里去掉双引号!
my_array[2]="/tmp/world"

# 现在执行就会成功了
"${my_array[@]}"

这时候Bash会把/tmp/hello/*直接展开成该目录下的所有文件,数组里的元素就变成了cp、/tmp/hello/hello.txt、/tmp/hello/world.txt、/tmp/world,和你直接敲cp /tmp/hello/* /tmp/world的效果完全一致。

方法2:用eval延迟展开(适合动态通配符场景)

如果你的通配符是动态生成的(比如来自变量、用户输入),或者你想在执行命令的时候再展开通配符,可以用eval来强制重新解析整个命令行:

mkdir -p /tmp/hello
echo "hello" > /tmp/hello/hello.txt
echo "world" > /tmp/hello/world.txt
mkdir -p /tmp/world

declare -a my_array=()
my_array[0]="cp"
my_array[1]="/tmp/hello/*"
my_array[2]="/tmp/world"

# 用eval执行,会自动展开通配符
eval "${my_array[@]}"

不过要特意提醒你:eval会完全解析整个命令字符串,如果数组里的内容来自不可信的输入(比如用户随便输入的内容),可能会执行恶意代码,所以这个方法一定要谨慎使用。

方法3:用compgen安全展开通配符(最安全的方式)

如果你想更安全地处理通配符,尤其是当通配符路径可能来自不可信来源时,可以用compgen提前把通配符展开成具体的文件路径,再放进数组:

mkdir -p /tmp/hello
echo "hello" > /tmp/hello/hello.txt
echo "world" > /tmp/hello/world.txt
mkdir -p /tmp/world

declare -a my_array=()
my_array[0]="cp"
# 用compgen -G展开通配符,把结果追加到数组
mapfile -t my_array < <(compgen -G "/tmp/hello/*")
my_array+=("/tmp/world")

"${my_array[@]}"

compgen -G只会匹配符合通配符的文件,不会执行任何额外的命令,所以安全性很高,适合处理不确定的通配符路径。

总结一下:

  • 固定路径的通配符,直接裸写赋值给数组就行;
  • 动态场景可以用eval,但要时刻警惕安全风险;
  • 追求安全的话,优先用compgen提前展开通配符。

备注:内容来源于stack exchange,提问作者stackbiz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.16 12:19:41