はじめに
S3バッチオペレーションを試したいなーと思ったのですが、インプットに以下の形式のcsvが必要なようでした。
CSV 形式のマニフェスト(バージョン ID なし)の例を以下に示します。
Examplebucket,objectkey1
Examplebucket,objectkey2
Examplebucket,objectkey3
Examplebucket,photos/jpgs/objectkey4
Examplebucket,photos/jpgs/newjersey/objectkey5
Examplebucket,object%20key%20with%20spacesバージョン ID を含む CSV 形式のマニフェストの例は次のとおりです。
Examplebucket,objectkey1,PZ9ibn9D5lP6p298B7S9_ceqx1n5EJ0p
Examplebucket,objectkey2,YY_ouuAJByNW1LRBfFMfxMge7XQWxMBF
Examplebucket,objectkey3,jbo9_jhdPEyB4RrmOxWS0kU0EoNrU_oI
Examplebucket,photos/jpgs/objectkey4,6EqlikJJxLTsHsnbZbSRffn24_eh5Ny4
Examplebucket,photos/jpgs/newjersey/objectkey5,imHf3FAiRsvBW_EHB8GOu.NHunHO1gVs
Examplebucket,object%20key%20with%20spaces,9HkPvDaZY5MVbMhn6TMn1YTb5ArQAo3w
jqや --query
オプションに苦手意識があったので、克服も兼ねて色々やってみました!
リファレンス
aws cliのバージョンは2.5.2です(アプデしないと・・・)
$ aws --version
aws-cli/2.5.2 Python/3.9.11
参考にしたドキュメントです
やってみた
準備
4つのオブジェクトが保存されているバケットを用意しました。
特定のバケットのオブジェクトを全量取得する
コマンド
aws s3api list-objects-v2 \
--bucket test-batch-ope-ito-log-a8f2ms
--bucket
対象バケット名を指定します
実行結果
$ aws s3api list-objects-v2 --bucket test-batch-ope-ito-log-a8f2ms
{
"Contents": [
{
"Key": "cap.jpg",
"LastModified": "2024-05-11T03:13:47+00:00",
"ETag": "\"5ee32753dd30e0580d8075ff5a228921\"",
"Size": 44575,
"StorageClass": "STANDARD"
},
{
"Key": "memo.txt",
"LastModified": "2024-05-11T03:13:14+00:00",
"ETag": "\"6436a6c961b90c90682e8fa52e03a6f2\"",
"Size": 1161,
"StorageClass": "STANDARD"
},
{
"Key": "shot.jpg",
"LastModified": "2024-05-11T03:32:50+00:00",
"ETag": "\"cd4854823f017f45f391161fb53e6c28\"",
"Size": 209678,
"StorageClass": "STANDARD"
},
{
"Key": "test.csv",
"LastModified": "2024-05-11T03:14:28+00:00",
"ETag": "\"d41d8cd98f00b204e9800998ecf8427e\"",
"Size": 0,
"StorageClass": "STANDARD"
}
]
}
4要素ある配列が帰ってきました!
バージョン情報は保持していないようです
特定のサイズのファイルだけを取得する
0kbのファイルを除外するケースを考えてみます。
コマンド
aws s3api list-objects-v2 --bucket test-batch-ope-ito-log-a8f2ms \
--query 'Contents[?Size > `0`]'
--query 'Contents[?Size > `0`]'
オブジェクト配列の各要素のSizeの値でfilterします
実行結果
$ aws s3api list-objects-v2 --bucket test-batch-ope-ito-log-a8f2ms --query 'Contents[?Size > `0`]'
[
{
"Key": "cap.jpg",
"LastModified": "2024-05-11T03:13:47+00:00",
"ETag": "\"5ee32753dd30e0580d8075ff5a228921\"",
"Size": 44575,
"StorageClass": "STANDARD"
},
{
"Key": "memo.txt",
"LastModified": "2024-05-11T03:13:14+00:00",
"ETag": "\"6436a6c961b90c90682e8fa52e03a6f2\"",
"Size": 1161,
"StorageClass": "STANDARD"
},
{
"Key": "shot.jpg",
"LastModified": "2024-05-11T03:32:50+00:00",
"ETag": "\"cd4854823f017f45f391161fb53e6c28\"",
"Size": 209678,
"StorageClass": "STANDARD"
}
]
配列の要素数が3つになって帰ってきました!
0byteのtest.csvをfilterの結果はじけてますね
特定の拡張子のファイルだけを取得する
aws cliのqueryでは正規表現は使えなさそうでした
jqでfilterします
コマンド
aws s3api list-objects-v2 \
--bucket test-batch-ope-ito-log-a8f2ms | \
jq -r '.Contents[] | select(.Key | endswith(".jpg"))'
jq -r '.Contents[] | select(.Key | endswith(".jpg"))'
Contents[]内の各要素に対し、Keyが".jpg"で終わるものをfilterします
実行結果
$ aws s3api list-objects-v2 --bucket test-batch-ope-ito-log-a8f2ms | jq -r '.Contents[] | select(.Key | endswith(".jpg"))'
{
"Key": "cap.jpg",
"LastModified": "2024-05-11T03:13:47+00:00",
"ETag": "\"5ee32753dd30e0580d8075ff5a228921\"",
"Size": 44575,
"StorageClass": "STANDARD"
}
{
"Key": "shot.jpg",
"LastModified": "2024-05-11T03:32:50+00:00",
"ETag": "\"cd4854823f017f45f391161fb53e6c28\"",
"Size": 209678,
"StorageClass": "STANDARD"
}
jpgである2ファイルのみ取得できました!
取得期間を指定する
特定の期間内にputされたオブジェクトのみを取得するケースを考えます
コマンド
aws s3api list-objects-v2 --bucket test-batch-ope-ito-log-a8f2ms \
--query 'Contents[?LastModified >=`2024-05-11T03:14`] | [?LastModified <= `2024-05-11T03:15`]'
--query 'Contents[?LastModified >=`2024-05-11T03:14`]
LastModifiedが特定の時間以降のオブジェクトをfilterしています
| [?LastModified <= `2024-05-11T03:15`]'
上記filter結果を、パイプ処理で再度filterしています
実行結果
$ aws s3api list-objects-v2 --bucket test-batch-ope-ito-log-a8f2ms --query 'Contents[?LastModified >=`2024-05-11T03:14`] | [?LastModified <= `2024-05-11T03:15`]'
[
{
"Key": "test.csv",
"LastModified": "2024-05-11T03:14:28+00:00",
"ETag": "\"d41d8cd98f00b204e9800998ecf8427e\"",
"Size": 0,
"StorageClass": "STANDARD"
}
]
特定の期間にPUTされたオブジェクトのみ取得できました!
ページネーションを行う
オブジェクトの量が多い場合、ページネーション処理が必要になります
コマンド
aws s3api list-objects-v2 --bucket test-batch-ope-ito-log-a8f2ms \
--max-items 2
--max-items 2
一度に取得するオブジェクト数の上限を意図的に下げ、ページネーションを確認します
実行結果
$ aws s3api list-objects-v2 --bucket test-batch-ope-ito-log-a8f2ms --max-items 2
{
"Contents": [
{
"Key": "cap.jpg",
"LastModified": "2024-05-11T03:13:47+00:00",
"ETag": "\"5ee32753dd30e0580d8075ff5a228921\"",
"Size": 44575,
"StorageClass": "STANDARD"
},
{
"Key": "memo.txt",
"LastModified": "2024-05-11T03:13:14+00:00",
"ETag": "\"6436a6c961b90c90682e8fa52e03a6f2\"",
"Size": 1161,
"StorageClass": "STANDARD"
}
],
"NextToken": "eyJDb250aW51YXRpb25Ub2tlbiI6IG51bGwsICJib3RvX3RydW5jYXRlX2Ftb3VudCI6IDJ9"
}
2つのオブジェクトのみが返却されました。
また、ページネーション用のNextTokenが合わせて返却されています
コマンド
aws s3api list-objects-v2 --bucket test-batch-ope-ito-log-a8f2ms \
--max-items 2 \
--starting-token eyJDb250aW51YXRpb25Ub2tlbiI6IG51bGwsICJib3RvX3RydW5jYXRlX2Ftb3VudCI6IDJ9
--starting-token eyJDb250aW51YXRpb25Ub2tlbiI6IG51bGwsICJib3RvX3RydW5jYXRlX2Ftb3VudCI6IDJ9
先ほど取得したTokenをリクエストに付与し、ページ処理を行います
$ aws s3api list-objects-v2 --bucket test-batch-ope-ito-log-a8f2ms --max-items 2 --starting-token eyJDb250aW51YXRpb25Ub2tlbiI6IG51bGwsICJib3RvX3RydW5jYXRlX2Ftb3VudCI6IDJ9
{
"Contents": [
{
"Key": "shot.jpg",
"LastModified": "2024-05-11T03:32:50+00:00",
"ETag": "\"cd4854823f017f45f391161fb53e6c28\"",
"Size": 209678,
"StorageClass": "STANDARD"
},
{
"Key": "test.csv",
"LastModified": "2024-05-11T03:14:28+00:00",
"ETag": "\"d41d8cd98f00b204e9800998ecf8427e\"",
"Size": 0,
"StorageClass": "STANDARD"
}
]
}
無事次の2オブジェクトが取得できました!
csv形式でoutputする
S3バッチオペレーションをしたかったことを思い出しました
S3バッチオペレーションのinputとなるcsvは以下の通りです
Examplebucket,objectkey1
Examplebucket,objectkey2
Examplebucket,objectkey3
Examplebucket,photos/jpgs/objectkey4
Examplebucket,photos/jpgs/newjersey/objectkey5
Examplebucket,object%20key%20with%20spaces
コマンド
aws s3api list-objects-v2 --bucket test-batch-ope-ito-log-a8f2ms \
--query 'Contents[?Size > `0`].[`replace_target`,Key]' \
--output text | sed 's/\t/,/g'
--query 'Contents[?Size > `0`].[`replace_target`,Key]'
Sizeが0以上のオブジェクトに対し、"replace_target"という固定文字列と、Keyを取得しています
ドキュメントにあるように、CSVの1カラム目はバケット名になるようなので、ファイル出力後にまとめて置換するために適当な文字列を1列目に指定しています
--output text | sed 's/\t/,/g'
平文形式で出力します。TSV形式で出力されるので、sedでCSVに変換します
実行結果
$ aws s3api list-objects-v2 --bucket test-batch-ope-ito-log-a8f2ms --query 'Contents[?Size > `0`].[`replace_target`,Key]' --output text | sed 's/\t/,/g'
replace_target,cap.jpg
replace_target,memo.txt
replace_target,shot.jpg
いいかんじ!
バージョンもあわせて出力する
バージョニングを有効化していたのですが、list-objects-v2
コマンドではバージョンが確認できませんでした
調べたところ、list-object-versions
というコマンドがあったので、そちらを使用してみました
コマンド
aws s3api list-object-versions \
--bucket test-batch-ope-ito-log-a8f2ms
実行結果
$ aws s3api list-object-versions --bucket test-batch-ope-ito-log-a8f2ms
{
"Versions": [
{
"ETag": "\"5ee32753dd30e0580d8075ff5a228921\"",
"Size": 44575,
"StorageClass": "STANDARD",
"Key": "cap.jpg",
"VersionId": "M0.fTixy2AUAXCD.idyCo_pdzlhiEwkC",
"IsLatest": true,
"LastModified": "2024-05-11T03:49:27+00:00",
"Owner": {
"DisplayName": "aaaaaaaaaaaaaaaaaaaa",
"ID": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}
},
{
"ETag": "\"6436a6c961b90c90682e8fa52e03a6f2\"",
"Size": 1161,
"StorageClass": "STANDARD",
"Key": "memo.txt",
"VersionId": "h5Mbjk9gs81zvkO2rXfe24MLctULprNp",
"IsLatest": true,
"LastModified": "2024-05-11T03:52:08+00:00",
"Owner": {
"DisplayName": "aaaaaaaaaaaaaaaaaaaa",
"ID": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}
},
{
"ETag": "\"cd4854823f017f45f391161fb53e6c28\"",
"Size": 209678,
"StorageClass": "STANDARD",
"Key": "shot.jpg",
"VersionId": "EQWuUogRNFOPt_npUfdTv9xFE1I2B146",
"IsLatest": true,
"LastModified": "2024-05-11T03:56:42+00:00",
"Owner": {
"DisplayName": "aaaaaaaaaaaaaaaaaaaa",
"ID": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}
},
{
"ETag": "\"cd4854823f017f45f391161fb53e6c28\"",
"Size": 209678,
"StorageClass": "STANDARD",
"Key": "shot.jpg",
"VersionId": "wzLukGRVNHbR4Bgh.wRoIYwEZ58big99",
"IsLatest": false,
"LastModified": "2024-05-11T03:50:27+00:00",
"Owner": {
"DisplayName": "aaaaaaaaaaaaaaaaaaaa",
"ID": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}
},
{
"ETag": "\"d41d8cd98f00b204e9800998ecf8427e\"",
"Size": 0,
"StorageClass": "STANDARD",
"Key": "test.csv",
"VersionId": "XbA2AR542oaNIZRxkW6LADyBZMm34r53",
"IsLatest": true,
"LastModified": "2024-05-11T03:49:27+00:00",
"Owner": {
"DisplayName": "aaaaaaaaaaaaaaaaaaaa",
"ID": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}
}
]
}
2世代あるshot.jpgがどちらのバージョンも表示されています、良いですね!
おわりに
jqや --query
コマンドのいい練習になりました!
他のAWS CLIコマンドでもガンガン使っていきたいです