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

如何在Shell/Bash脚本中用变量压缩多后缀文件?

问题根源:Shell扩展时机的坑

你碰到的这个问题本质是Shell的扩展顺序在搞鬼:当你把带{*.json,*.yaml,*.db}的字符串赋值给变量时,Shell不会自动解析这个大括号扩展和通配符,只会把它原封不动地当成一个单一的字符串参数传给tar——而这个字面路径显然不存在,所以报错。但直接写在tar命令里时,Shell会先完成大括号扩展和文件名匹配,把它转换成所有符合条件的文件路径列表,再传给tar,所以第二条命令能正常工作。

解决方法(按推荐程度排序)

1. 使用Bash数组(最安全,推荐)

Bash数组能在赋值时就完成大括号和通配符的扩展,并且能正确处理带空格的文件名(这是字符串变量做不到的)。修改后的脚本如下:

#!/bin/bash
BackupPath="/root/upfOps/te"
# 简化判断目录的写法
[ ! -d "$BackupPath" ] && mkdir -p "$BackupPath"

# 用数组存储所有匹配的文件,赋值时自动完成扩展
MYSC_FILES=(/home/mysc/cmin02sms/etc/{*.json,*.yaml,*.db})

# 用数组展开语法传给tar,确保每个文件都是单独的参数
tar vczf "$BackupPath/t1.tar.gz" "${MYSC_FILES[@]}"

这里的"${MYSC_FILES[@]}"是关键:它会把数组里的每个元素作为独立的参数传递,即使文件名包含空格、特殊字符也不会出错。

2. 用eval强制扩展(不推荐,仅当路径绝对安全时用)

如果你坚持要用字符串变量,可以用eval命令强制Shell重新解析变量里的扩展语法。但要注意:如果路径里包含空格、引号、$等特殊字符,eval可能会执行意外的命令,有安全风险。示例:

#!/bin/sh
BackupPath="/root/upfOps/te"
if [ ! -d "$BackupPath" ]; then
    mkdir -p "$BackupPath"
fi

MYSC_JSON_YAML_DB="/home/mysc/cmin02sms/etc/{*.json,*.yaml,*.db}"
# 用eval让Shell重新解析变量中的扩展语法
eval tar vczf "$BackupPath/t1.tar.gz" "$MYSC_JSON_YAML_DB"

3. 函数封装扩展(仅作参考)

你也可以用函数来返回扩展后的路径列表,但同样存在处理特殊文件名的问题,不如数组靠谱:

#!/bin/bash
BackupPath="/root/upfOps/te"
[ ! -d "$BackupPath" ] && mkdir -p "$BackupPath"

# 函数返回匹配的文件路径
get_mysc_targets() {
    echo /home/mysc/cmin02sms/etc/{*.json,*.yaml,*.db}
}

# 命令替换获取扩展后的路径
tar vczf "$BackupPath/t1.tar.gz" $(get_mysc_targets)

总结

优先选择Bash数组的方案,它是处理这类多文件路径场景最稳妥的方式,能避免各种边界问题。eval尽量少用,除非你完全确定路径里没有任何危险字符。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 18:35:27