11
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

「S3はオブジェクトストレージ」の意味、本当に理解できてますか?~見事にハマった俺の屍を超えて行け~

Posted at

AWSの資格勉強(SAAなど)をしていると、必ず出てくる定番の知識があります。

「S3はオブジェクトストレージであり、EFSのようなファイルストレージとは異なり、ディレクトリ階層構造を持たない」

私も丸暗記して、「またこれかー、サービス問題やわ」とドヤ顔していました。
しかし、いざ実務でPythonスクリプトを書いていた時、この知識の意味を本当には理解していなかったことを、エラーログに叩きつけられることになりました。

今日は、私がS3の「幻のディレクトリ」に躓き、IndexError で時間を溶かした話を共有します。

1. そもそも「S3にはディレクトリがない」とは?

私たちが普段PCで扱うファイルシステム(やEFS)は、本物の「木構造」をしています。フォルダの中にフォルダがあり、その中にファイルがあります。

しかし、S3は「バケット」という巨大なプールの中に、ファイル(オブジェクト)がフラットに浮いているだけです。

AWSコンソールを見ると、綺麗にフォルダ分けされているように見えますよね?

my-bucket/
 └ logs/
    └ 2025/
       └ 10/
          └ app.log

でも、S3から見れば、これは「logsフォルダの中の2025フォルダの中の...」ではなく、 logs/2025/10/app.log というめちゃくちゃ長い名前(キー)がついた1個のファイル」 でしかありません。スラッシュ(/)はただの文字です。

ここまでは、教科書通りの知識です。

2. コンソール機能が生む「ディレクトリオブジェクト」の罠

ここからが実務の落とし穴です。
S3にはディレクトリがないはずなのに、AWSコンソールには親切にも 「フォルダの作成」というボタンがあります。

ディレクトリがないのにフォルダを作る とは?

実はこれ、キーの末尾が / で終わる、中身が空っぽの0バイトオブジェクト を作成しているんです。
これを便宜上「ディレクトリオブジェクト」と呼びます。

ここで認識のズレが起きる

  • SDK/CLIでアップロードした場合:
    prefix/file.txt というキーでアップロードすれば、間のフォルダオブジェクトは作られない
  • コンソールでポチポチ作った場合:
    prefix/ という実体のない0バイトオブジェクトが生成されてしまう

厄介なことにこれら、コンソール上での見た目は完全に同じなのです。
S3のコンソールは、人間が扱いやすいよう徹底的に「ファイルシステムっぽく」振る舞おうとするらしく、ありがた迷惑。

真実を知るには、CLIでlsを叩くしかないです。

この「目に見えない0バイトの幽霊」が、後のコード実行時に牙を剥きます。

3. 事件発生:探索スクリプトが落ちた

私はS3上のログファイルを探索し、ファイル名から正規表現でIPアドレスなどを抽出するPythonスクリプトを書いていました。

# イメージ:特定の日付プレフィックス以下の全オブジェクトを取得
prefix = "logs/2025/11/04/"
objects = bucket.objects.filter(Prefix=prefix)

for item in objects:
    # ファイル名から必要な情報を抽出(ここで事故る)
    # 'logs/2025/11/04/ip-10-xxx.gz' みたいなのを期待している
    match = re.findall(r'ip-[0-9]+', item.key)[0] 
    print(match)

テスト環境で実行したところ、突然の IndexError: list index out of range
「えっ、ログファイルなら絶対このパターンを含んでいるはずなのに、なんでマッチしないの?」

原因は「フォルダそのもの」だった

デバッグして判明したのは、bucket.objects.filter が返したリストの中に、ログファイルだけでなく、
logs/2025/11/04/ という「フォルダ(ディレクトリオブジェクト)」そのもの
が含まれていたことでした。

  1. S3「ヘイ、prefix に一致するオブジェクトを持ってきたぞ」
  2. コード「ありがとう。1つ目は... logs/2025/11/04/app.log だな。正規表現マッチ!」
  3. コード「2つ目は... logs/2025/11/04/ だな。正規表現マッチ... しない! リストが空だ! [0] にアクセスできない! 死!

「S3はオブジェクトストレージ(=フォルダなんてない)」と頭では分かっていたのに、コードを書くときは「返ってくるのはファイルだけでしょ」というファイルストレージ的な感覚が抜けきっていなかったわけです。

4. 教訓と対策

コードでの回避策

S3をプログラムで走査するときは、「フォルダオブジェクトが混ざっているかもしれない」と常に疑う必要があります。
一番簡単な対策は、末尾の / をチェックすることです。

for item in bucket.objects.filter(Prefix=prefix):
    # ディレクトリオブジェクト(フォルダ)ならスキップ!
    if item.key.endswith('/'):
        continue
        
    # 以降、ファイルに対する処理
    # ...

この2行を入れるだけで、コンソールで作られたフォルダも、そうでない場合も安全に処理できます。

運用のベストプラクティス

そして根本的な対策として、「S3ではむやみにフォルダを作らない(ディレクトリを掘らない)」ことが重要です。

  • aaa/bbb/ccc/ddd.xml を置きたいなら、コンソールで aaa 作って bbb 作って...とやる必要はありません。
  • アップロード時にファイルのキー(名前)を aaa/bbb/ccc/ddd.xml に指定すれば、勝手にその階層にあるように見せてくれます。

未経験文系新卒エンジニアとしてはどうしてもCLIよりもGUIのほうが扱いやすい気がして、目の前の「フォルダの作成」に飛びついてしまったのでした。
(普通に考えると、GUIでポチポチするよりもCLIでザーッと一括登録する方が楽です)

まとめ

  • 知識: S3にはディレクトリはない。あるのは「キー」だけ。
  • 現実: コンソールの「フォルダ作成」は、/ で終わる空オブジェクトを作っている。
  • ハマりポイント: プログラムで一覧取得すると、ファイルに混じって「フォルダオブジェクト」が返ってきて、処理を破壊することがある。

「S3はオブジェクトストレージ」。
SAAの勉強中はただの暗記ワードでしたが、エラーと格闘したおかげで、ようやくこの言葉の本当の意味が五臓六腑に染み渡りました。

みなさんが何かの拍子でこの記事を思い出してエラーを回避してくれたらうれしいです。

11
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?