S3批量上传工具 s3-bulk-upload

这是一个用于自动化批量上传文件到亚马逊S3云存储的技能。它通过文件名的首字符(字母、数字、其他)自动创建并归类到对应的前缀目录(如a/、b/、0-9/、_other/),实现文件在S3中的有序组织。支持单文件上传、批量上传、高效的同步模式、多种存储类别选择以及上传验证,是进行云端文件管理和数据迁移的实用工具。关键词:AWS S3,批量上传,文件组织,前缀分类,云存储,数据迁移,自动化脚本。

AWS 0 次安装 0 次浏览 更新于 2/24/2026

name: s3-bulk-upload description: 通过首字符前缀自动组织文件,批量上传到S3。 version: 1.0.0 metadata: openclaw: requires: env: - AWS_ACCESS_KEY_ID - AWS_SECRET_ACCESS_KEY bins: - aws primaryEnv: AWS_ACCESS_KEY_ID emoji: “\U0001F4E6” install: - kind: brew formula: awscli bins: [aws]

S3 批量上传

使用首字符前缀自动组织文件上传到S3(例如:a/apple.txtb/banana.txt0-9/123.txt)。

快速开始

使用附带的脚本进行批量上传:

# 基本上传
./s3-bulk-upload.sh ./files my-bucket

# 试运行预览
./s3-bulk-upload.sh ./files my-bucket --dry-run

# 使用同步模式(对大量文件更快)
./s3-bulk-upload.sh ./files my-bucket --sync

# 指定存储类别
./s3-bulk-upload.sh ./files my-bucket --storage-class STANDARD_IA

先决条件

验证AWS凭证已配置:

aws sts get-caller-identity

如果失败,请确保设置了 AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY,或通过 aws configure 配置。

组织逻辑

文件根据其文件名的第一个字符进行组织:

首字符 前缀
a-z 小写字母(例如:a/b/
A-Z 小写字母(例如:a/b/
0-9 0-9/
其他 _other/

单文件上传

使用自动前缀上传单个文件:

FILE="example.txt"
BUCKET="my-bucket"

# 根据首字符计算前缀
FIRST_CHAR=$(echo "${FILE}" | cut -c1 | tr '[:upper:]' '[:lower:]')
if [[ "$FIRST_CHAR" =~ [a-z] ]]; then
  PREFIX="$FIRST_CHAR"
elif [[ "$FIRST_CHAR" =~ [0-9] ]]; then
  PREFIX="0-9"
else
  PREFIX="_other"
fi

aws s3 cp "$FILE" "s3://${BUCKET}/${PREFIX}/${FILE}"

批量上传

上传目录中的所有文件:

SOURCE_DIR="./files"
BUCKET="my-bucket"

for FILE in "$SOURCE_DIR"/*; do
  [ -f "$FILE" ] || continue
  BASENAME=$(basename "$FILE")
  FIRST_CHAR=$(echo "$BASENAME" | cut -c1 | tr '[:upper:]' '[:lower:]')

  if [[ "$FIRST_CHAR" =~ [a-z] ]]; then
    PREFIX="$FIRST_CHAR"
  elif [[ "$FIRST_CHAR" =~ [0-9] ]]; then
    PREFIX="0-9"
  else
    PREFIX="_other"
  fi

  aws s3 cp "$FILE" "s3://${BUCKET}/${PREFIX}/${BASENAME}"
done

高效批量同步

对于大型上传,使用符号链接暂存文件,然后使用 aws s3 sync

SOURCE_DIR="./files"
STAGING_DIR="./staging"
BUCKET="my-bucket"

# 创建具有前缀结构的暂存目录
rm -rf "$STAGING_DIR"
mkdir -p "$STAGING_DIR"

for FILE in "$SOURCE_DIR"/*; do
  [ -f "$FILE" ] || continue
  BASENAME=$(basename "$FILE")
  FIRST_CHAR=$(echo "$BASENAME" | cut -c1 | tr '[:upper:]' '[:lower:]')

  if [[ "$FIRST_CHAR" =~ [a-z] ]]; then
    PREFIX="$FIRST_CHAR"
  elif [[ "$FIRST_CHAR" =~ [0-9] ]]; then
    PREFIX="0-9"
  else
    PREFIX="_other"
  fi

  mkdir -p "$STAGING_DIR/$PREFIX"
  ln -s "$(realpath "$FILE")" "$STAGING_DIR/$PREFIX/$BASENAME"
done

# 将整个暂存目录同步到S3
aws s3 sync "$STAGING_DIR" "s3://${BUCKET}/"

# 清理
rm -rf "$STAGING_DIR"

验证

按前缀列出文件:

BUCKET="my-bucket"
PREFIX="a"

aws s3 ls "s3://${BUCKET}/${PREFIX}/" --recursive

生成所有已上传文件的清单:

BUCKET="my-bucket"

aws s3 ls "s3://${BUCKET}/" --recursive | awk '{print $4}'

统计每个前缀的文件数:

BUCKET="my-bucket"

for PREFIX in {a..z} 0-9 _other; do
  COUNT=$(aws s3 ls "s3://${BUCKET}/${PREFIX}/" --recursive 2>/dev/null | wc -l | tr -d ' ')
  [ "$COUNT" -gt 0 ] && echo "$PREFIX: $COUNT files"
done

错误处理

常见问题及解决方案:

错误 原因 解决方案
AccessDenied 权限不足 检查IAM策略是否对存储桶拥有 s3:PutObject 权限
NoSuchBucket 存储桶不存在 创建存储桶或检查存储桶名称拼写
InvalidAccessKeyId 凭证错误 验证 AWS_ACCESS_KEY_ID 是否正确
ExpiredToken 会话令牌过期 刷新凭证或重新认证

批量上传前测试存储桶访问权限:

BUCKET="my-bucket"
echo "test" | aws s3 cp - "s3://${BUCKET}/_test_access.txt" && \
  aws s3 rm "s3://${BUCKET}/_test_access.txt" && \
  echo "存储桶访问正常"

存储类别

使用存储类别优化成本:

# 标准(默认)
aws s3 cp file.txt s3://bucket/prefix/file.txt

# 不频繁访问(存储成本更低,检索收费)
aws s3 cp file.txt s3://bucket/prefix/file.txt --storage-class STANDARD_IA

# Glacier即时检索(归档且快速访问)
aws s3 cp file.txt s3://bucket/prefix/file.txt --storage-class GLACIER_IR

# 智能分层(根据访问模式自动优化)
aws s3 cp file.txt s3://bucket/prefix/file.txt --storage-class INTELLIGENT_TIERING

在批量上传循环中添加 --storage-class,以优化不常访问文件的成本。