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

如何下载数百万个S3文件并实时压缩后保存?

实现S3桶文件实时下载并压缩的方案

首先得指出你给出的示例命令的问题:aws s3 cp --recursive s3://bucket | gzip > file 没法工作,因为aws s3 cp --recursive会直接把文件下载到本地磁盘,而不是将文件内容输出到标准输出(stdout),所以管道接不到任何有效数据。要实现边下载边实时压缩,我们需要把每个文件的内容输出到stdout,再统一收集压缩,同时还要考虑是否保留原文件的目录结构。

下面分两种常见场景给出解决方案:

场景1:将所有文件内容合并为一个压缩包(不保留目录结构)

如果不需要还原原有的文件层级,只是把所有文件的内容合并成一个gzip压缩文件,可以用以下命令:

# 替换为你的S3桶名称
BUCKET_NAME="your-bucket-name"

aws s3 ls "s3://$BUCKET_NAME/" --recursive --output json | jq -r '.Key' | while read -r file_key; do
    # 将每个文件的内容输出到stdout
    aws s3 cp "s3://$BUCKET_NAME/$file_key" -
done | gzip > all-s3-files.gz

细节说明:

  • 用--output json结合jq提取文件路径(Key字段),可以避免文件名包含空格、特殊字符时的解析错误
  • aws s3 cp ... -中的-表示将文件内容输出到标准输出,而不是保存到本地文件
  • 所有文件的内容会通过管道传递给gzip,实时压缩后保存到all-s3-files.gz

场景2:保留原目录结构的tar.gz压缩包(推荐)

如果需要解压后还原S3桶内的文件层级,推荐将文件打包为tar.gz格式,同时实时压缩:

# 替换为你的S3桶名称
BUCKET_NAME="your-bucket-name"
# 最终压缩包文件名
BACKUP_FILE="s3-bucket-backup.tar.gz"

# 创建一个命名管道,用于tar和gzip的流式传输
mkfifo tar_pipe
# 启动gzip进程,从管道读取tar归档内容并压缩
gzip < tar_pipe > "$BACKUP_FILE" &

# 遍历所有文件,将每个文件添加到tar归档中
aws s3 ls "s3://$BUCKET_NAME/" --recursive --output json | jq -r '.Key' | while read -r file_key; do
    # 将下载的文件内容作为指定路径的文件添加到tar归档
    aws s3 cp "s3://$BUCKET_NAME/$file_key" - | tar --append --file=tar_pipe --transform="s|^|$file_key|"
done

# 关闭管道,等待gzip进程完成压缩
rm tar_pipe
wait

细节说明:

  • 命名管道(mkfifo)让tar和gzip可以流式协作,不需要占用额外磁盘空间存储未压缩的tar包
  • tar --transform参数会将从stdin读取的内容映射为$file_key路径的文件,确保归档内保留原S3的目录结构
  • 最后用wait等待gzip进程完成,避免压缩包损坏

优化建议:提升处理速度

如果桶内有上百万个文件,串行处理会很慢,可以考虑以下优化:

  1. 增加AWS CLI的并发数:在aws s3 cp命令中添加--parallel参数(需要AWS CLI v2+),同时设置--max-concurrent-requests提升下载并发:
    aws s3 cp "s3://$BUCKET_NAME/$file_key" - --parallel --max-concurrent-requests 20
    
  2. 避免文件名解析错误:始终用--output json+jq的方式提取文件路径,不要用awk处理原始输出(原始输出的文件名如果有空格会被分割)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 14:42:39