Overview
In my previous article, I created an S3 bucket and uploaded a single object. This time I'm organizing that bucket: creating folders, uploading multiple files at once, moving an object between folders, and finally deleting the bucket.
Along the way I'll explain a fact that trips up many people: Amazon S3 doesn't have folders. What the console shows you is something else, and once you understand it, a lot of S3 behavior starts to make sense.
By the end of this article, you'll be able to:
- Create folders (and nested folders) in a bucket
- Upload several files in one go
- Explain what a prefix is and how it differs from a real folder
- Move an object from one folder to another, and understand what S3 does behind the scenes
- Empty and delete a bucket correctly
Where we're starting
I'm using the same bucket from the first article, aws-lab1-rahimah, which currently holds one object, datacenter.png.
Step 1: Create a folder
Inside the bucket, I clicked Create folder. The form asks for a folder name, so I entered food. Notice the hint under the field: folder names can't contain a /, because S3 uses that character itself to mark folder boundaries (more on that shortly).
The page also has a Server-side encryption section with two options:
- Don't specify an encryption key: the folder uses the bucket's default encryption setting. I kept this one.
- Specify an encryption key: choose a key just for this folder object.
Two warnings on that page are worth reading. The encryption settings apply only to the folder object itself, not to the files you later put inside it. And if your bucket policy requires a specific encryption key, you must specify that same key here, or folder creation will fail.
After clicking Create folder, S3 confirmed with a green banner, and the bucket now lists Objects (2): datacenter.png and food/. The Type column shows Folder for food/.
Opening food/ shows an empty folder: Objects (0).
So what is a "folder" in S3?
Here's the important part. S3 uses a flat structure. There is a bucket, and inside it there are objects. That's it. There are no real directories nested inside each other.
What the console calls a folder is built from three ideas:
-
Key: the full name of an object. A file I upload into
food/has the keyfood/burger.png, not justburger.png. -
Prefix: the beginning part of a key. For
food/burger.png, the prefix isfood/. -
Delimiter: the character that separates the parts of a key. In S3, it's the forward slash
/.
When you click Create folder, S3 creates a tiny, empty object whose key ends in / (here, food/). The console then uses the / delimiter to display objects with the same prefix as if they lived in a folder. It's a presentation layer that makes a flat store feel familiar.
Coming from Azure? It works much the same way in Blob Storage. A container holds blobs in a flat namespace, and "folders" are just
/characters in blob names (virtual directories). Real directories only appear when you enable the hierarchical namespace on a storage account (Data Lake Storage Gen2).
Step 2: Upload multiple files into the folder
With food/ open, I clicked Upload, then Add files. In the file picker, I selected three images at once: burger.png, cake.png and pizza.png.
The Upload page lists all three (3 total, 8.2 MB), and the Destination is now s3://aws-lab1-rahimah/food/. That path is the S3 URI of the folder, which is exactly the prefix the files will receive.
I clicked Upload, and the status page reported Upload succeeded: 3 files, 8.2 MB, 100%, with 0 failures.
Back at the bucket's root, there are still only two entries, datacenter.png and food/. The three new files live inside the folder.
Opening food/ shows Objects (3): burger.png, cake.png and pizza.png, each with the Standard storage class and its own last-modified time.
Step 3: Open a file and see the prefix in the URL
To prove the prefix idea, I selected burger.png and clicked Open. The image loaded in a new tab, and the address bar shows the key right in the path:
https://aws-lab1-rahimah.s3.eu-north-1.amazonaws.com/food/burger.png?X-Amz-Algorithm=...
See food/burger.png? That's the full key. There's no directory lookup involved. The long X-Amz-... parameters after it are the presigned URL signature I covered in the first article, which is why the file opens even though the bucket is private.
Step 4: Create a nested folder
Next, I wanted a sub-folder. Inside food/, I clicked Create folder again and named it menu. S3 confirmed with Successfully created folder "menu".
Now food/ contains burger.png, cake.png, pizza.png and the new menu/ folder. The key of that new folder is food/menu/, which is just a longer prefix. Nesting folders only means chaining more prefixes with /.
I deleted the datacenter.png and created an empty folder called menu/.
Step 5: Move a file into the new folder
I wanted cake.png to live in menu/. I ticked the checkbox next to cake.png and opened the Actions menu. It offers a lot of options:
- Download as and Share with a presigned URL
- Calculate total size
- Copy and Move
- Query with S3 Select
- Under Edit actions: Rename object, Edit storage class, Edit server-side encryption, Edit tags, and Make public using ACL
I chose Move. The page opens with an important note at the top: this action creates a copy of the object with a new last-modified date, and depending on the bucket's versioning status, a delete marker will be inserted or the original object will be permanently deleted. Keep that sentence in mind, because it explains what move really does (more below).
The Destination field expects an S3 path in the format s3://bucket-name/optional-prefix/. You can type it, or click Browse S3 and navigate to the folder. I used Browse S3, went into aws-lab1-rahimah > food/, and selected the menu/ folder.
The browser also lets you open menu/ to check what's inside. At this point, it says there are no objects under this path, which is expected for a brand-new folder.
After clicking Choose destination, the form filled itself in:
-
Destination:
s3://aws-lab1-rahimah/food/menu/ -
Destination bucket name:
aws-lab1-rahimah -
Destination prefix:
food/menu/
Below that, Destination details shows the settings of the target bucket: Bucket Versioning is Disabled, Default encryption is SSE-S3, and Object Lock is Disabled. Because versioning is off, the console shows a recommendation to enable it. The Specified objects table confirms the one file being moved, cake.png (2.7 MB).
Last, Additional copy settings offers three choices. I kept the default, Copy source settings, which carries over the source object's storage class, tags, metadata and encryption. The other two let you skip those settings or specify new ones.
I clicked Move. The status page reported Successfully moved objects: 1 object, 2.7 MB, with 0 failures.
Checking the results:
-
food/now shows Objects (3):burger.png,menu/andpizza.png.cake.pngis gone from here.
-
menu/shows Objects (1):cake.png.
What "move" really does
Look at the Last modified time on the moved file. It changed to a newer timestamp than when I originally uploaded it. That's the giveaway: S3 has no true "move" or "rename" operation. The console does two steps for you:
-
Copy the object to the new key (
food/cake.pngbecomesfood/menu/cake.png). - Delete the original.
This matters for two reasons. First, because versioning was disabled on this bucket, the original was permanently deleted. If versioning were enabled, S3 would insert a delete marker instead, and the old version could be recovered. Second, the same logic applies to Rename object: it's also a copy followed by a delete, since a rename just means giving the object a new key.
For anything you can't afford to lose, enable versioning before you start moving things around.
Step 6: Delete the bucket
When the lab is finished, clean up so nothing lingers in your account. On the General purpose buckets page, I selected the radio button next to aws-lab1-rahimah. The toolbar offers Copy ARN, Empty, Delete and Create bucket.
I clicked Delete first, and S3 stopped me with this error: "This bucket is not empty. Buckets must be empty before they can be deleted." The page also asks you to type the bucket's name to confirm deletion, but the Delete bucket button stays disabled until the bucket is empty.
The solution is to empty the bucket first:
- Click Empty bucket (on that error banner, or Empty on the bucket list). Or go back to the bucket, select the objects and click delete.
- Confirm by typing
permanently deletewhen prompted, then click Empty. This can never be retrieved because versioning is not enabled.
- Return to Delete bucket, type
aws-lab1-rahimahin the confirmation field, and click Delete bucket.
Emptying removes every object, including the folder objects, and it cannot be undone. That's why S3 makes you confirm twice.
Key takeaways
-
S3 has no real folders. A "folder" is a prefix that the console displays using the
/delimiter. - An object's key is its full name, including the prefix.
burger.pnginsidefood/has the keyfood/burger.png. - Creating a folder just creates a small, empty object whose key ends in
/. - You can upload several files at once, and they all receive the destination folder's prefix.
- Move and Rename are really copy + delete, which is why the last-modified date changes.
- With versioning disabled, a move permanently removes the original. With versioning enabled, a delete marker is added instead.
- A bucket must be emptied before it can be deleted.
- In Azure terms, this is the same flat-namespace model as Blob Storage virtual directories.
Conclusion
Folders in S3 are a convenience, not a structure. Once you think in terms of keys and prefixes, things like moving files, setting lifecycle rules and writing IAM policies for food/* all make sense, because they all work on prefixes.
Next up in this series, I'll look at S3 permissions and what it takes to make an object public safely.
Which S3 feature should I cover after that: versioning, lifecycle rules or static website hosting? Let me know in the comments.























Top comments (1)
A detail that surprises people: the
food/"folder" doesn't even need to exist.Upload a file straight to the key
food/menu/cake.pngusing the CLI:aws s3 cp cake.png s3://aws-lab1-rahimah/food/menu/cake.pngThe console will still show
food/andmenu/as folders, even though neither was ever created. They're just prefixes, and the console draws the folders for you. The Create folder button only adds a tiny empty placeholder object whose key ends in/.It also explains why "renaming a folder" is a bigger job than it looks. There's nothing to rename, so changing
food/tomeals/means S3 has to copy and delete every object under that prefix, one by one. A prefix with 10,000 files means 10,000 copy + delete operations.Have you ever hit that on a large bucket? And which should I cover next: versioning, lifecycle rules or static website hosting?