如何在Bash脚本中为AWS CLI打标签操作动态生成prefix参数值
解决方案
错误原因
S3的
list-objects/list-objects-v2接口的--prefix参数仅支持纯字符串前缀匹配,不支持通配符语法,你传入的/base/*/foo/会被AWS识别为包含*字符的字面量路径,自然无法匹配到实际存在的对象,后续调用打标签接口时就会触发NoSuchKey报错。
实现脚本
用Bash循环结合S3的公共前缀列举能力即可实现需求,相比全量遍历所有对象效率更高,也能准确匹配所有/base/[用户名]/foo/路径下的文件:
#!/bin/bash # 配置参数 BUCKET="myBucket" TAG_KEY="myKey" TAG_VALUE="myValue" BASE_PREFIX="/base/" # 标签JSON提前定义,避免转义问题 TAG_JSON=$(jq -n --arg k "$TAG_KEY" --arg v "$TAG_VALUE" '{"TagSet": [{"Key": $k, "Value": $v}]}') # 第一步:列举/base/下所有用户级的公共前缀(比如/base/user1/、/base/user2/) aws s3api list-objects-v2 \ --bucket "$BUCKET" \ --prefix "$BASE_PREFIX" \ --delimiter "/" \ --query 'CommonPrefixes[].Prefix' \ --output text | tr '\t' '\n' | while read -r USER_PREFIX; do # 拼接得到foo目录的完整前缀 FOO_PREFIX="${USER_PREFIX}foo/" # 第二步:列举当前foo前缀下的所有文件,批量打标签 # 这里加了--delimiter "/"避免遍历foo下的子目录,如果需要处理子目录可以删掉这个参数 aws s3api list-objects-v2 \ --bucket "$BUCKET" \ --prefix "$FOO_PREFIX" \ --delimiter "/" \ --query 'Contents[].Key' \ --output text | tr '\t' '\n' | grep -v '^$' | \ # 用xargs并行处理,-P 10表示同时跑10个打标签任务,可根据需求调整并发数 xargs -P 10 -n 1 -I {} aws s3api put-object-tagging \ --bucket "$BUCKET" \ --key "{}" \ --tagging "$TAG_JSON" done
说明
- 依赖
jq工具处理JSON格式的标签配置,避免手写JSON的转义错误,大部分系统可通过包管理器直接安装(比如yum install jq/apt install jq/brew install jq) - 用
list-objects-v2的--delimiter参数只列举公共前缀,不需要遍历存储桶全量对象,面对大存储桶时效率提升非常明显 - xargs的
-P参数开启并发处理,远快于单循环逐次调用打标签接口 - 如果需要处理
foo目录下的子目录文件,删掉第二个list-objects-v2命令里的--delimiter "/"参数即可
内容的提问来源于stack exchange,提问作者Timothy Clotworthy
相关产品推荐
相关产品推荐

