100万個から10月分を探す
ネットショップが、毎日のアクセスログを S3 バケットに保存しています。何年も続けたので、ファイルは100万個に近づきました。10月分だけが欲しいとき、全部を開くわけにはいきません。
S3 では、名前の始まりが同じファイルだけの一覧を頼めます。このレッスンでは、S3 のバケットをプレフィックスで一覧する方法を学びます。
このレッスンのゴール
メモ
プレフィックスを使って、バケットの中のファイルを探すことができる。
キーワード
| ことば | いみ | れい |
|---|---|---|
| オブジェクト | 保存された1つのファイルと、その情報 | |
| キー | バケットの中での、オブジェクトの完全な名前 | logs/2026-10-01/web.log |
| プレフィックス | キーの始まりの部分 | |
| 区切り文字 | キーを段に分ける文字 | / |
| 共通プレフィックス | 複数のキーが共有する、フォルダのような始まり |
学生が入力するセルは、このプレビューでは空白です。
バケットはオブジェクトを持つ
バケットはオブジェクトを持ちます。オブジェクトは、ファイルのバイト列と、大きさなどの情報です。各オブジェクトには、完全な名前のキーがあり、探すときはキーを使います。
中に、フォルダの木はありません。バケットは、キーを並べた平らな一覧です。logs/2026-10-01/web.log は、スラッシュを含む、長い名前にすぎません。
実行: 一覧を読む
answer = {
"Name": "shop-logs",
"Prefix": "",
"KeyCount": 4,
"IsTruncated": False,
"Contents": [
{"Key": "images/cat.png", "Size": 4, "StorageClass": "STANDARD"},
{"Key": "logs/2026-10-01/web.log", "Size": 17, "StorageClass": "STANDARD"},
{"Key": "logs/2026-10-02/web.log", "Size": 6, "StorageClass": "STANDARD"},
{"Key": "readme.txt", "Size": 5, "StorageClass": "STANDARD"},
],
}
for item in answer["Contents"]:
print(item["Key"], item["Size"])
# 全オブジェクトの Size を足して、合計を表示しましょう。
よくある間違い
注意
S3 のバケットに本物のフォルダがある、と考える人が多いです。ありません。スラッシュは、キーの中の1文字にすぎません。複数のキーが同じ始まりのとき、一覧にフォルダのように見えるだけで、最後のオブジェクトを消すと、フォルダも消えます。
プレフィックスで始まるキーを探す
バケットを一覧するとき、プレフィックスを渡せます。すると S3 は、それで始まるキーだけを返します。プレフィックス logs/2026-10-01/ なら、1日分のログだけが見つかります。
絞り込むのは S3 なので、コードがバケット全部を読む必要はありません。答えは、送ったプレフィックスをくり返し、見つけたキーの数を KeyCount に入れます。
実行: プレフィックスで絞る
keys = [
"images/cat.png",
"logs/2026-10-01/db.log",
"logs/2026-10-01/web.log",
"logs/2026-10-02/web.log",
"readme.txt",
]
prefix = "logs/2026-10-01/"
found = []
for key in keys:
if key.startswith(prefix):
found.append(key)
print("KeyCount:", len(found))
print(found)
# prefix を "logs/" に変えて実行しましょう。キーは何個になりますか。
区切り文字でフォルダにまとめる
logs/ の直下のフォルダだけが欲しく、ファイルは要らないとします。プレフィックスに加えて、区切り文字 / を渡します。S3 は、プレフィックスのあとの最初のスラッシュで、各キーを切ります。
切り口が同じキーは、共通プレフィックスとして、CommonPrefixes に1回だけ入ります。プレフィックスのあとにスラッシュがないキーは、これまでどおり Contents に入ります。
実行: logs/ の下のフォルダ
keys = [
"logs/2026-10-01/db.log",
"logs/2026-10-01/web.log",
"logs/2026-10-02/web.log",
]
prefix = "logs/"
common = []
for key in keys:
rest = key[len(prefix):]
slash = rest.find("/")
if slash != -1:
folder = prefix + rest[:slash + 1]
if folder not in common:
common.append(folder)
prefixes = []
for one in common:
prefixes.append({"Prefix": one})
answer = {"Prefix": prefix, "Delimiter": "/", "CommonPrefixes": prefixes}
print(answer)
# keys に "logs/2026-10-03/web.log" を足して、もう一度実行しましょう。
ないキーの答えは2通り
ないオブジェクトを1つ求めると、エラーになります。ただし、呼び出しによって違います。get_object の Code は NoSuchKey です。情報だけを求める head_object は、名前を入れる本体がないので、Code が "404" になります。
どちらも状態は 404 です。両方をまとめて調べたいときは、状態を調べます。
クラウドラボで試す
クラウドラボは、S3、SQS、DynamoDB の練習用の複製です。バーの ラボを起動 を押してから、下の各コマンドの 実行 を押します。本物の AWS コマンドラインを使うので、同じ言葉が本物のアカウントでも通じます。最後の2つのコマンドは、CommonPrefixes にフォルダー logs/2026-10-01/ が入った一覧と、そのあとのエラー NoSuchKey を表示します。この手順は練習です。下の課題はふつうの Python のままなので、ラボなしでも解けます。
作り物のキーとラボのアドレスを設定する
export AWS_ACCESS_KEY_ID=test AWS_SECRET_ACCESS_KEY=test AWS_DEFAULT_REGION=us-east-1 AWS_ENDPOINT_URL=http://cloud:4566ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
バケットを作る
aws s3 mb s3://prefix-labここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
スラッシュのあるキーでオブジェクトを保存する
aws s3 cp /etc/hostname s3://prefix-lab/logs/2026-10-01/web.logここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
プレフィックスと区切り文字で一覧する
aws s3api list-objects-v2 --bucket prefix-lab --prefix logs/ --delimiter /ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
ないキーをたずねる
aws s3api get-object --bucket prefix-lab --key nothing.txt /dev/nullここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。