March 19, 2025

Amazon S3のフォルダオブジェクトはファイルシステムのフォルダとは異なる

S3のフォルダオブジェクトはファイルシステムのフォルダとは異なる

Amazon S3 の「フォルダオブジェクト」は一般的なファイルシステムの「フォルダ」と別物らしいので調べてみた。

フォルダオブジェクトとプレフィックス

  • フォルダオブジェクト
    • オブジェクト名が’/‘で終わる、サイズ0のオブジェクト
  • プレフィックス
    • オブジェクト名の接頭辞
    • ‘/‘で終わる

s3://hoge/fuga/tako/ika.log の場合、

  • hoge = バケット名
  • fuga/tako/ = ika.log のプレフィックス
    • fuga/ と tako/ はフォルダオブジェクトの場合がある

見分け方

AWSのWeb GUIでS3を見るとフォルダオブジェクトとプレフィックスは区別が付かないけど、AWS CLI からなら見分けられる

  • aws s3 ls <バケット名>/hogehoge/
    • サイズ0の名前のないオブジェクトがあったらフォルダオブジェクト
    • なかったらプレフィックス
  • aws s3api head-object --bucket <バケット名> --prefix hogehoge/
    • ContentLengthが0だったらフォルダオブジェクト
    • フォルダとして見えているのに404が返ってきたらプレフィックス
  • aws s3api list-objects-v2 --bucket <バケット名> --prefix hogehoge/
    • Sizeが0でKeyが/で終わるコンテンツがあったらフォルダオブジェクト
    • なかったらプレフィックス

例えば以下は、nissy-lab-testというバケットの hogehoge/ は404が返ってきたのでプレフィックス

user1@server1:~$ aws s3api head-object --bucket nissy-lab-test --key hogehoge/

An error occurred (404) when calling the HeadObject operation: Not Found

以下はContentLengthが0で、オプションで渡したキーが「/」で終わっているのでフォルダオブジェクト

​user1@server1:~$ aws s3api head-object --bucket nissy-lab-test --key hogehoge/
{
    "AcceptRanges": "bytes",
    "LastModified": "2025-03-19T10:00:00+00:00",
    "ContentLength": 0,
    "ETag": "\"d41dXXXXXXXXXXXXXXXXXXXXXXXXXXXX\"",
    "VersionId": "tlTiXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "ContentType": "application/x-directory; charset=UTF-8",
    "ServerSideEncryption": "AES256",
    "Metadata": {}
}

以下はContentLengthが0だけど、オプションで渡したキーは「/」で終わっていないので通常のオブジェクト

​user1@server1:~$ aws s3api head-object --bucket nissy-lab-test --key hogehoge
{
    "AcceptRanges": "bytes",
    "LastModified": "2025-03-19T10:00:00+00:00",
    "ContentLength": 0,
    "ETag": "\"d41dXXXXXXXXXXXXXXXXXXXXXXXXXXXX\"",
    "VersionId": "yQj_XXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "ContentType": "binary/octet-stream",
    "ServerSideEncryption": "AES256",
    "Metadata": {}
}

実際に作って試してみる

フォルダオブジェクト

  1. hogehoge/ というフォルダオブジェクトもプレフィックスも存在しない状態で
    user1@server1:~$ aws s3 ls nissy-lab-test/
    user1@server1:~$ aws s3api head-object --bucket nissy-lab-test --key hogehoge/
       
    An error occurred (404) when calling the HeadObject operation: Not Found
    user1@server1:~$ aws s3api list-objects-v2 --bucket nissy-lab-test --prefix hogehoge/
    {
        "RequestCharged": null
    }
    
  2. フォルダオブジェクト hogehoge/ を作る
    user1@server1:~$ aws s3api put-object --bucket nissy-lab-test --key hogehoge/
    {
        "ETag": "\"d41dXXXXXXXXXXXXXXXXXXXXXXXXXXXX\"",
        "ServerSideEncryption": "AES256",
        "VersionId": "u2ojXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
    }
    
  3. オブジェクト hogehoge/hoge.txt を作る
    user1@server1:~$ aws s3api put-object --bucket nissy-lab-test --key hogehoge/hoge.txt
    {
        "ETag": "\"d41dXXXXXXXXXXXXXXXXXXXXXXXXXXXX\"",
        "ServerSideEncryption": "AES256",
        "VersionId": "1W58XXXXXXXXXXXXXXXXXXXXXXXXXXXX"
    }
    
  4. hogehoge/ はフォルダオブジェクトであり、 hogehoge/hoge.txt はオブジェクトである
    user1@server1:~$ aws s3 ls nissy-lab-test/
                               PRE hogehoge/
    user1@server1:~$ aws s3 ls nissy-lab-test/hogehoge/
    2025-03-19 19:00:00          0
    2025-03-19 19:00:00          0 hoge.txt
    user1@server1:~$ aws s3api head-object --bucket nissy-lab-test --key hogehoge/
    {
        "AcceptRanges": "bytes",
        "LastModified": "2025-03-19T10:00:00+00:00",
        "ContentLength": 0,
        "ETag": "\"d41dXXXXXXXXXXXXXXXXXXXXXXXXXXXX\"",
        "VersionId": "J3itXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
        "ContentType": "binary/octet-stream",
        "ServerSideEncryption": "AES256",
        "Metadata": {}
    }
    user1@server1:~$ aws s3api head-object --bucket nissy-lab-test --key hogehoge/hoge.txt
    {
        "AcceptRanges": "bytes",
        "LastModified": "2025-03-19T10:00:00+00:00",
        "ContentLength": 0,
        "ETag": "\"d41dXXXXXXXXXXXXXXXXXXXXXXXXXXXX\"",
        "VersionId": "1W58XXXXXXXXXXXXXXXXXXXXXXXXXXXX",
        "ContentType": "binary/octet-stream",
        "ServerSideEncryption": "AES256",
        "Metadata": {}
    }
    user1@server1:~$ aws s3api list-objects-v2 --bucket nissy-lab-test --prefix hogehoge/
    {
        "Contents": [
            {
                "Key": "hogehoge/",
                "LastModified": "2025-03-19T00:00:00+00:00",
                "ETag": "\"d41dXXXXXXXXXXXXXXXXXXXXXXXXXXXX\"",
                "ChecksumAlgorithm": [
                    "CRC64NVME"
                ],
                "Size": 0,
                "StorageClass": "STANDARD"
            },
            {
                "Key": "hogehoge/hoge.txt",
                "LastModified": "2025-03-19T00:00:00+00:00",
                "ETag": "\"d41dXXXXXXXXXXXXXXXXXXXXXXXXXXXX\"",
                "ChecksumAlgorithm": [
                    "CRC64NVME"
                ],
                "Size": 0,
                "StorageClass": "STANDARD"
            }
        ],
        "RequestCharged": null
    }
    
  5. hogehoge/ はフォルダオブジェクトなので、WebGUIからフォルダを作成できない。
  6. フォルダオブジェクトを削除しても hogehoge/hoge.txt のプレフィックスとして残る。
    user1@server1:~$ aws s3 rm s3://nissy-lab-test/hogehoge/
    delete: s3://nissy-lab-test/hogehoge/
    user1@server1:~$ aws s3 ls nissy-lab-test/
                               PRE hogehoge/
    user1@server1:~$ aws s3 ls nissy-lab-test/hogehoge/
    2025-03-19 19:00:00          0 hoge.txt
    user1@server1:~$ aws s3api head-object --bucket nissy-lab-test --key hogehoge/
       
    An error occurred (404) when calling the HeadObject operation: Not Found
    user1@server1:~$ aws s3api head-object --bucket nissy-lab-test --key hogehoge/hoge.txt
    {
        "AcceptRanges": "bytes",
        "LastModified": "2025-03-19T10:00:00+00:00",
        "ContentLength": 0,
        "ETag": "\"d41dXXXXXXXXXXXXXXXXXXXXXXXXXXXX\"",
        "VersionId": "1W58XXXXXXXXXXXXXXXXXXXXXXXXXXXX",
        "ContentType": "binary/octet-stream",
        "ServerSideEncryption": "AES256",
        "Metadata": {}
    }
    
  7. フォルダオブジェクトとしての hogehoge/ は削除したので、WebGUIからフォルダを作成できる。

プレフィックス

  1. fugafuga/ というフォルダオブジェクトもプレフィックスも存在しない
    user1@server1:~$ aws s3 ls nissy-lab-test
                               PRE hogehoge/
    user1@server1:~$ aws s3api head-object --bucket nissy-lab-test --key fugafuga/
       
    An error occurred (404) when calling the HeadObject operation: Not Found
    user1@server1:~$ aws s3api list-objects-v2 --bucket nissy-lab-test --prefix fugafuga/
    {
        "RequestCharged": null
    }
    
  2. オブジェクト fugafuga/fuga.txt を作る
    user1@server1:~$ aws s3api put-object --bucket nissy-lab-test --key fugafuga/fuga1.txt
    {
        "ETag": "\"d41dXXXXXXXXXXXXXXXXXXXXXXXXXXXX\"",
        "ServerSideEncryption": "AES256",
        "VersionId": "8nGoXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
    }
    
  3. fugafuga/ はプレフィックスであり、 fugafuga/fuga.txt はオブジェクトである
    user1@server1:~$ aws s3 ls nissy-lab-test/
                               PRE fugafuga/
                               PRE hogehoge/
    user1@server1:~$ aws s3 ls nissy-lab-test/fugafuga/
    2025-03-19 19:10:00          0 fuga1.txt
    user1@server1:~$ aws s3api head-object --bucket nissy-lab-test --key fugafuga/
       
    An error occurred (404) when calling the HeadObject operation: Not Found
    user1@server1:~$ aws s3api list-objects-v2 --bucket nissy-lab-test --prefix fugafuga/
    {
        "Contents": [
            {
                "Key": "fugafuga/fuga1.txt",
                "LastModified": "2025-03-19T19:10:00+00:00",
                "ETag": "\"d41dXXXXXXXXXXXXXXXXXXXXXXXXXXXX\"",
                "ChecksumAlgorithm": [
                    "CRC64NVME"
                ],
                "Size": 0,
                "StorageClass": "STANDARD"
            }
        ],
        "RequestCharged": null
    }
    
  4. fugafuga/ はプレフィックスなので、WebGUIからフォルダを作成できる。
  5. 再び fugafuga/ を削除してただのプレフィックスにすることもできる。
    user1@server1:~$ aws s3 rm s3://nissy-lab-test/fugafuga/
    delete: s3://nissy-lab-test/fugafuga/
    user1@server1:~$ aws s3 ls nissy-lab-test/fugafuga/
    2025-03-19 19:10:00          0 fuga1.txt
    

一次情報源

© 2020 nissy-lab.com