批量将当前目录下每个子文件夹分别压缩为独立的 tar.gz 文件

本文详细介绍在Linux中批量将子文件夹压缩为独立tar.gz文件的方法。涵盖基础for循环、指定目录、排除特定文件夹、利用find动态筛选、通过parallel或xargs实现并行加速、日志记录、完整性校验及pigz多线程压缩等进阶技巧,并提供综合脚本模板,高效完成目录打包任务。

作者:zhuge··预计阅读 14 分钟·4 阅读·0 评论
批量将当前目录下每个子文件夹分别压缩为独立的 tar.gz 文件

我们有时需要将多个独立的目录各自打包成压缩包,以便按需传输或备份。本文介绍一套专业的 Linux 命令方案,涵盖从基础到进阶的各种场景,并给出可直接使用的脚本模板。


1. 基础需求:逐个压缩子文件夹

若当前目录下存在多个子文件夹(如 project_a/, project_b/, data/ 等),希望将它们各自压缩为独立的 .tar.gz,且文件名加上自定义前缀(例如 www_),可用以下 for 循环实现:

for dir in */; do
    # 去掉末尾的斜杠,得到纯目录名
    dirname="${dir%/}"
    # 打包压缩,文件名格式:前缀 + 目录名 + .tar.gz
    tar czvf "www_${dirname}.tar.gz" "$dir"
done
  • */ 会匹配当前目录下的所有子目录(不包含文件)。
  • dirname="${dir%/}" 用于去除末尾的 /,得到干净的目录名。
  • tar czvf 创建压缩包,z 表示 gzip 压缩,v 显示过程,f 指定文件名。

执行后,会生成类似 www_project_a.tar.gzwww_project_b.tar.gz 等文件。


2. 指定压缩目标(避免压缩所有目录)

如果只想压缩指定的几个目录,可以显式列出目录名(或使用数组):

dirs=("project_a" "project_b" "data")
for dir in "${dirs[@]}"; do
    tar czvf "www_${dir}.tar.gz" "./$dir"
done

3. 高级选项:排除某些子目录

有些目录(如 cache/tmp/*.git)不需要打包,可在 tar 命令中添加 --exclude 选项:

for dir in */; do
    dirname="${dir%/}"
    tar czvf "www_${dirname}.tar.gz" \
        --exclude="$dirname/cache" \
        --exclude="$dirname/tmp" \
        --exclude="*.git" \
        "$dir"
done

注意--exclude 的模式是相对于打包根目录的,且支持通配符。


4. 使用 find 动态获取目录列表(更灵活)

若目录名不符合简单通配,或需要过滤条件(如只压缩修改时间在 7 天内的目录),可以借助 find

find . -maxdepth 1 -type d ! -name "." -mtime -7 | while read -r dir; do
    dirname=$(basename "$dir")
    tar czvf "www_${dirname}.tar.gz" "$dir"
done
  • -maxdepth 1 只查找当前目录下的直接子目录。
  • ! -name "." 排除当前目录本身。
  • -mtime -7 只处理 7 天内修改过的目录(可按需修改)。

5. 并行压缩加速(利用多核 CPU)

当目录数量多或数据量大时,串行压缩可能较慢。可使用 GNU Parallelxargs 并行执行 tar,大幅提升速度。

5.1 使用 parallel

# 安装 parallel(若未安装)
sudo apt install parallel   # Debian/Ubuntu
sudo yum install parallel   # CentOS/RHEL

# 并行压缩
ls -d */ | parallel 'dir={}; dirname={%/}; tar czvf "www_${dirname}.tar.gz" "$dir"'

5.2 使用 xargs -P

ls -d */ | xargs -P 4 -I {} sh -c 'dir={}; dirname=${dir%/}; tar czvf "www_${dirname}.tar.gz" "$dir"'
  • -P 4 表示同时运行 4 个压缩进程,可根据 CPU 核心数调整。

6. 保存日志与错误处理

压缩过程可能产生大量输出,建议将标准输出和错误分别记录:

for dir in */; do
    dirname="${dir%/}"
    tar czvf "www_${dirname}.tar.gz" "$dir" \
        > "logs/${dirname}.log" 2>&1
done

提前创建 logs/ 目录,以便追踪每个包的压缩详情。


7. 校验压缩包完整性

压缩完成后,建议校验每个包是否可正常读取,避免损坏:

for tarfile in www_*.tar.gz; do
    if tar tzf "$tarfile" > /dev/null 2>&1; then
        echo "$tarfile OK"
    else
        echo "$tarfile CORRUPTED" >&2
    fi
done

也可生成 MD5 校验文件供后续比对:

md5sum www_*.tar.gz > checksums.md5

8. 清理原始文件夹(可选)

若确认压缩包无误,且原始目录不再需要,可删除它们(慎用!):

# 先确认压缩包存在且可读,再删除原目录
for dir in */; do
    dirname="${dir%/}"
    if [ -f "www_${dirname}.tar.gz" ]; then
        rm -rf "$dir"
    fi
done

9. 一键脚本:综合示例

将上述功能整合为一个 Bash 脚本 batch_tar.sh,支持参数化前缀、排除模式、并行数等:

#!/bin/bash
# 批量压缩子目录为独立的 tar.gz

PREFIX="www_"
EXCLUDE_PATTERNS=("cache" "tmp" "*.log")
PARALLEL_JOBS=2

# 获取目录列表(排除隐藏目录)
dirs=( $(ls -d */ 2>/dev/null | sed 's|/$||') )

if [ ${#dirs[@]} -eq 0 ]; then
    echo "No subdirectories found."
    exit 1
fi

compress_dir() {
    local dir=$1
    local tarfile="${PREFIX}${dir}.tar.gz"
    local exclude_opts=()
    for pattern in "${EXCLUDE_PATTERNS[@]}"; do
        exclude_opts+=(--exclude="${dir}/${pattern}")
    done
    echo "Compressing $dir -> $tarfile"
    tar czf "$tarfile" "${exclude_opts[@]}" "$dir"
}

export -f compress_dir
export PREFIX EXCLUDE_PATTERNS

# 并行执行
printf "%s\n" "${dirs[@]}" | xargs -P "$PARALLEL_JOBS" -I {} bash -c 'compress_dir "$@"' _ {}

echo "All done."

赋予执行权限并运行:

chmod +x batch_tar.sh
./batch_tar.sh

10. 进阶:使用 pigz 加速压缩

默认的 gzip 是单线程,可用 pigz(并行 gzip)替代,在多核服务器上显著提速。配合 tar 使用:

# 安装 pigz
sudo apt install pigz   # Debian/Ubuntu

# 压缩时调用 pigz
tar -I pigz -cvf "www_${dirname}.tar.gz" "$dir"

注意:-I pigz 指定压缩程序,输出文件后缀仍为 .tar.gz 但实际是 pigz 压缩。


总结

需求推荐命令
基本批量压缩for dir in */; do tar czvf "前缀${dir%/}.tar.gz" "$dir"; done
指定目录列表使用数组或显式列表
排除某些子目录--exclude 选项
并行加速parallelxargs -P
压缩后校验tar tzf 测试
极速压缩(多核)配合 pigz

相关文章

评论

加载中...