Bash脚本执行rm排除指定文件命令被自动加单引号报错如何解决
问题根因
你观察到的单引号是set -x调试模式的输出格式,仅用于标识单个命令参数的边界,并不是Bash真的为命令添加了引号。报错的核心原因有两个:
- 默认配置下,如果当前目录没有符合
!(*.psf|*.fdf|siesta|*.log)匹配规则的文件,这个扩展通配符不会展开,会直接作为字符串传递给rm,导致rm找不到对应文件 - 你只开启了
extglob扩展通配选项,没有配套开启nullglob选项处理匹配为空的场景
修复后的脚本
#!/bin/bash set -euxo pipefail # 同时开启扩展通配和空匹配选项 shopt -s extglob nullglob for BASE in Adenina Citocina Guanina Timina do # 用pushd/popd替代手动切换路径,更稳妥 pushd "${BASE}" > /dev/null || exit 1 # 加-f参数避免无文件可删时rm报错 rm -f !(*.psf|*.fdf|siesta|*.log) popd > /dev/null || exit 1 done
关键修改说明
- 新增
shopt -s nullglob:当通配符匹配不到任何文件时,直接展开为空字符串,不会把通配符本身作为参数传给rm - 给rm添加
-f参数:既可以跳过不存在的文件不报错,也不会在无文件可删时抛出异常 - 用
pushd/popd替代手动保存当前路径切换,避免路径变量异常导致的切换错误 - 所有变量用双引号包裹,避免路径含空格时执行异常
兼容替代方案(无需开启extglob)
如果你所在的环境不支持extglob扩展,可以直接用find命令实现同样效果,不需要切换目录:
#!/bin/bash set -euxo pipefail for BASE in Adenina Citocina Guanina Timina do find "./${BASE}" -maxdepth 1 -type f \ ! -name "*.psf" \ ! -name "*.fdf" \ ! -name "siesta" \ ! -name "*.log" \ -delete done
内容的提问来源于stack exchange,提问作者Carlos Andrés del Valle
相关产品推荐
相关产品推荐

