Amazon S3
Java
File Deletion
Directory Management
Cloud Storage

Delete files, directories and buckets in amazon s3 java

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Deleting data in Amazon S3 is simple at the API level, but the terminology can be misleading. S3 stores objects in buckets and does not have real directories in the filesystem sense. What looks like a directory is just a key prefix, and a bucket can be deleted only after every relevant object is removed. In Java, the AWS SDK makes these operations manageable once you model them correctly.

Delete a single object

If you know the exact bucket and key, deleting one object is straightforward with the AWS SDK for Java 2.x.

java
1import software.amazon.awssdk.regions.Region;
2import software.amazon.awssdk.services.s3.S3Client;
3import software.amazon.awssdk.services.s3.model.DeleteObjectRequest;
4
5public class DeleteOneObject {
6    public static void main(String[] args) {
7        try (S3Client s3 = S3Client.builder().region(Region.US_EAST_1).build()) {
8            s3.deleteObject(DeleteObjectRequest.builder()
9                    .bucket("my-bucket")
10                    .key("reports/2025-03-01.csv")
11                    .build());
12        }
13    }
14}

This removes the object identified by that exact key. If the object does not exist, S3 generally treats the delete as idempotent rather than throwing a "file not found" style error.

Delete what people call a directory

In S3, a "directory" is just a prefix such as reports/2025/. To delete it, you list the objects under that prefix and delete those objects.

java
1import java.util.ArrayList;
2import java.util.List;
3import software.amazon.awssdk.regions.Region;
4import software.amazon.awssdk.services.s3.S3Client;
5import software.amazon.awssdk.services.s3.model.Delete;
6import software.amazon.awssdk.services.s3.model.DeleteObjectsRequest;
7import software.amazon.awssdk.services.s3.model.ListObjectsV2Request;
8import software.amazon.awssdk.services.s3.model.ObjectIdentifier;
9import software.amazon.awssdk.services.s3.paginators.ListObjectsV2Iterable;
10
11public class DeletePrefix {
12    public static void main(String[] args) {
13        try (S3Client s3 = S3Client.builder().region(Region.US_EAST_1).build()) {
14            String bucket = "my-bucket";
15            String prefix = "reports/2025/";
16
17            List<ObjectIdentifier> toDelete = new ArrayList<>();
18
19            ListObjectsV2Iterable pages = s3.listObjectsV2Paginator(
20                    ListObjectsV2Request.builder()
21                            .bucket(bucket)
22                            .prefix(prefix)
23                            .build());
24
25            pages.contents().forEach(obj ->
26                    toDelete.add(ObjectIdentifier.builder().key(obj.key()).build()));
27
28            if (!toDelete.isEmpty()) {
29                s3.deleteObjects(DeleteObjectsRequest.builder()
30                        .bucket(bucket)
31                        .delete(Delete.builder().objects(toDelete).build())
32                        .build());
33            }
34        }
35    }
36}

This is the right mental model for deleting a pseudo-directory in S3: delete every object whose key starts with the prefix.

Delete a bucket

A bucket cannot be deleted until it is empty. That means you must first delete its objects, and if versioning is enabled, you must also delete its object versions and delete markers.

For a non-versioned empty bucket, the final step is:

java
1import software.amazon.awssdk.regions.Region;
2import software.amazon.awssdk.services.s3.S3Client;
3import software.amazon.awssdk.services.s3.model.DeleteBucketRequest;
4
5public class DeleteBucketExample {
6    public static void main(String[] args) {
7        try (S3Client s3 = S3Client.builder().region(Region.US_EAST_1).build()) {
8            s3.deleteBucket(DeleteBucketRequest.builder()
9                    .bucket("my-empty-bucket")
10                    .build());
11        }
12    }
13}

If the bucket still contains objects or versions, S3 rejects the request.

Versioned buckets need extra care

This is where many deletion scripts fail. In a versioned bucket, deleting the current visible object is not enough. Old versions and delete markers still count toward bucket contents. If your goal is to remove the bucket entirely, you must enumerate and delete versions as well.

That is not a Java quirk; it is core S3 behavior. The bucket is not truly empty until all versions and markers are gone.

Batch deletion is usually better than one-by-one deletion

For prefixes with many objects, repeated single-object delete calls are slow and noisy. deleteObjects lets you send multiple keys in one request, which is usually the better default for cleanup tools.

You still need pagination on the listing side, though, because large prefixes may span many result pages.

Common Pitfalls

The biggest mistake is thinking S3 directories are real directories. They are only key prefixes, so deleting a "directory" means deleting objects whose keys begin with that prefix.

Another issue is trying to delete a bucket before emptying it. S3 does not allow that, and versioned buckets add another layer because old versions must be removed too.

Developers also forget pagination when deleting large prefixes. A bucket listing call may return only part of the objects, leaving cleanup incomplete.

Finally, make sure the IAM permissions match the operation. Object deletion, listing, and bucket deletion each require the appropriate S3 permissions.

Summary

  • S3 deletes objects by bucket and key, not by filesystem path.
  • A "directory" in S3 is a prefix, so you delete all objects under that prefix.
  • Buckets can be deleted only after they are completely empty.
  • Versioned buckets require deleting versions and delete markers as well.
  • For large cleanups, combine paginated listing with batch delete requests.

Course illustration
Course illustration

All Rights Reserved.