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

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

原因分析

原脚本的循环逻辑存在缺陷:

  1. 脚本试图通过"${startdir[@]}"/*/一次性展开所有目标目录下的子目录,但Bash在默认配置下,当通配符(/*/)匹配不到任何子目录时,不会展开通配符,而是将目标目录/*/作为一个完整字符串传递给循环变量。
  2. 当/root/Archive/EKS/data/*/不存在时,循环变量sub_dir被赋值为这个无效路径,zip命令处理该路径时出现意外行为,最终打包了/root/Archive/EKS/data目录本身。
  3. 第二个目标目录下存在子目录,通配符正常展开为各个子目录路径,因此脚本能正确处理。

解决方法

采用两层循环的结构,先遍历每个目标目录,再单独遍历该目录下的子目录,同时启用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 04:35:32