List an Amazon S3 Folder One Level at a Time

This example shows how to list the contents of an Amazon S3 folder the way a file browser does: only the sub-folders and objects directly under a prefix, one page at a time. S3 keys are flat, so by default a listing returns every key below the prefix. Setting a delimiter on the AmazonS3FileSystem makes S3 roll the keys below each sub-folder up into a common prefix instead, and isTruncated() with nextBatch() walk through the pages S3 returns.

Java Code Listing

package com.northconcepts.datapipeline.examples.amazons3;

import com.northconcepts.datapipeline.amazons3.AmazonS3FileSystem;
import com.northconcepts.datapipeline.amazons3.S3ObjectListing;
import com.northconcepts.datapipeline.amazons3.S3ObjectSummary;

public class ListAnAmazonS3FolderOneLevelAtATime {

    private static final String ACCESS_KEY = "YOUR ACCESS KEY";
    private static final String SECRET_KEY = "YOUR SECRET KEY";
    private static final String BUCKET = "YOUR BUCKET";
    private static final String FOLDER = "output/";

    public static void main(String[] args) throws Throwable {
        AmazonS3FileSystem s3 = new AmazonS3FileSystem()
                .setBasicAWSCredentials(ACCESS_KEY, SECRET_KEY)
                .setDelimiter(AmazonS3FileSystem.FOLDER_DELIMITER);
        s3.open();
        try {
            S3ObjectListing listing = s3.listFolder(BUCKET, FOLDER);
            while (true) {
                for (String prefix : listing.getCommonPrefixes()) {
                    System.out.println("folder  " + prefix);
                }
                for (S3ObjectSummary object : listing.getObjectSummaries()) {
                    System.out.println("object  " + object.getKey() + "  " + object.getSize() + " bytes");
                }
                if (!listing.isTruncated()) {
                    break;
                }
                listing = s3.nextBatch(listing);
            }
        } finally {
            s3.close();
        }
    }

}

Code Walkthrough

  1. ACCESS_KEY, SECRET_KEY and BUCKET identify the account and bucket; FOLDER is the prefix to list (output/).
  2. An AmazonS3FileSystem is created with basic credentials and setDelimiter(AmazonS3FileSystem.FOLDER_DELIMITER) so every listing uses / as the folder separator. Without a delimiter listFolder() would return every nested key.
  3. s3.open() connects to S3.
  4. s3.listFolder(BUCKET, FOLDER) returns an S3ObjectListing. getCommonPrefixes() holds the sub-folders directly under the prefix and getObjectSummaries() the objects, each an S3ObjectSummary with its key and size in bytes.
  5. When isTruncated() is true there are more results; s3.nextBatch(listing) fetches the next page and the loop continues until the last page.
  6. s3.close() in the finally block disconnects.

Console Output

For a bucket with a dated archive folder and one file under output/ the output looks like this:

folder  output/2026-01/
folder  output/2026-02/
object  output/trades.csv  48213 bytes
Mobile Analytics