You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

Shell脚本执行报错:sh运行时出现Bad substitution错误

解决sh执行脚本时的Bad substitution错误

你遇到的问题根源很明确:你的脚本用了Bash专属的字符串替换语法 ${f// /_},但当你用sh test.sh执行时,sh在很多Linux系统里默认指向的是Dash(而非Bash),Dash并不支持这种参数展开语法,所以就抛出了Bad substitution错误。

下面给你两种可行的解决方案,适配你要配置到crontab的需求:

方案1:强制用Bash执行脚本(推荐)

其实crontab里完全可以指定用Bash来运行脚本,不需要局限于sh。你只需要做两件事:

  1. 保持你的原脚本不变(因为它本身是合法的Bash脚本):
    #!/bin/bash
    for f in /home/admin1/abc/*.kmz
    do
        mv "$f" "${f// /_}"
    done
    
  2. 在crontab里配置命令时,明确调用Bash路径(通常是/bin/bash):
    # 示例:每天凌晨2点执行脚本
    0 2 * * * /bin/bash /path/to/your/test.sh
    

这样既保留了Bash简洁的语法,又能在crontab里正常运行。

方案2:修改脚本为sh兼容写法

如果因为某些限制必须用sh执行,那就要把Bash专属的替换语法改成POSIX兼容的写法,比如用sed来处理文件名替换:

#!/bin/sh
for f in /home/admin1/abc/*.kmz
do
    # 用sed把所有空格替换成下划线
    new_name=$(echo "$f" | sed 's/ /_/g')
    # 执行重命名,注意引号要保留,避免文件名含特殊字符出问题
    mv "$f" "$new_name"
done

或者用awk也能实现同样的效果:

new_name=$(echo "$f" | awk '{gsub(/ /,"_"); print}')

额外的crontab注意事项

在crontab里运行脚本时,还要注意两个常见坑:

  • 路径问题:crontab的默认PATH比较窄,建议脚本里用绝对路径(比如/bin/mv而不是mv),或者在脚本开头添加PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin来扩展环境变量。
  • 测试先行:可以先手动用sh test.sh运行修改后的脚本,确认重命名正常;或者在脚本里把mv改成echo mv,先打印出要执行的命令,验证替换逻辑没问题再实际执行。

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

火山引擎 最新活动