Bash脚本批量打包目录异常:部分目录打包结果不符合预期
Bash脚本打包目录结果不一致的原因与解决方法
问题现象
编写的Bash脚本期望对startdir数组中指定的两个目录下的子目录分别打包,但执行结果不一致:
- 处理
/root/Archive/EKS/data时,直接将该目录本身打包为data.zip,未处理其子目录 - 处理
/root/Elasticsearch/data时,正常对每个子目录生成对应的zip文件
原脚本
#!/bin/bash startdir=( "/root/Archive/EKS/data" "/root/Elasticsearch/data" ) for sub_dir in "${startdir[@]}"/*/ ; do echo "$sub_dir" zip "${sub_dir%/}".zip "$sub_dir" echo "clean" done
执行日志(bash -x输出)
/root/Archive/EKS/data adding: root/Archive/EKS/data/ (stored 0%) /root/Elasticsearch/data/abc-cleanup-es-index/ adding: root/Elasticsearch/data/abc-cleanup-es-index/ (stored 0%) /root/Elasticsearch/data/abc-export-cw-logs/ adding: root/Elasticsearch/data/abc-export-cw-logs/ (stored 0%) /root/Elasticsearch/data/abc-log-to-es/ adding: root/Elasticsearch/data/abc-log-to-es/ (stored 0%)
异常输出(第一次迭代)
└─# pwd /root/Archive/EKS ┌──(root㉿user)-[~/Archive/EKS] └─# ls -lrt drwxr-xr-x 6 root root 4096 May 20 12:18 data -rw-r--r-- 1 root root 198 May 20 13:26 data.zip
正常输出(第二次迭代)
┌──(root㉿user)-[~/Elasticsearch/data] └─# ls -lrt drwxr-xr-x 2 root root 4096 May 17 14:43 abc-dir1 drwxr-xr-x 2 root root 4096 May 17 14:43 abc-dir2 drwxr-xr-x 2 root root 4096 May 17 14:43 abc-dir3 -rw-r--r-- 1 root root 230 May 20 13:26 abc-dir1.zip -rw-r--r-- 1 root root 240 May 20 13:26 abc-dir2.zip -rw-r--r-- 1 root root 244 May 20 13:26 abc-dir3.zip
原因分析
原脚本的循环逻辑存在缺陷:
- 脚本试图通过
"${startdir[@]}"/*/一次性展开所有目标目录下的子目录,但Bash在默认配置下,当通配符(/*/)匹配不到任何子目录时,不会展开通配符,而是将目标目录/*/作为一个完整字符串传递给循环变量。 - 当
/root/Archive/EKS/data/*/不存在时,循环变量sub_dir被赋值为这个无效路径,zip命令处理该路径时出现意外行为,最终打包了/root/Archive/EKS/data目录本身。 - 第二个目标目录下存在子目录,通配符正常展开为各个子目录路径,因此脚本能正确处理。
解决方法
采用两层循环的结构,先遍历每个目标目录,再单独遍历该目录下的子目录,同时启用nullglob选项避免处理无效路径:
#!/bin/bash # 启用nullglob:当通配符无匹配时返回空列表,而非保留通配符字符串 shopt -s nullglob startdir=( "/root/Archive/EKS/data" "/root/Elasticsearch/data" ) # 第一层循环:遍历每个目标目录 for dir in "${startdir[@]}"; do # 第二层循环:遍历当前目标目录下的所有子目录 for sub_dir in "$dir"/*/; do echo "$sub_dir" zip "${sub_dir%/}".zip "$sub_dir" echo "clean" done done # 关闭nullglob(可选,恢复默认行为) shopt -u nullglob
说明
shopt -s nullglob:确保当目标目录下没有子目录时,内层循环不会执行,避免处理无效路径。- 两层循环的结构明确了遍历逻辑,先处理每个目标目录,再处理其下的子目录,逻辑更清晰,结果更可控。
内容的提问来源于stack exchange,提问作者Gowmi
相关产品推荐
相关产品推荐

