AWS
S3
CLI
Recursive
Cloud Storage

Recursive list s3 bucket contents with AWS CLI

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

Recursively listing an S3 bucket with the AWS CLI is usually as simple as adding --recursive to aws s3 ls. The real value comes from understanding what that command shows, when to switch to s3api for structured output, and how to narrow the listing with prefixes so you do not drown in object names.

Use aws s3 ls --recursive for Human-Readable Output

The fastest way to walk an entire bucket is:

bash
aws s3 ls s3://my-bucket --recursive

That prints every object key beneath the bucket, including objects that look like they are inside nested folders. S3 does not actually have directories in the filesystem sense. It has object keys with prefixes, and the CLI renders those prefixes in a directory-like way.

If you only want one logical subtree, add the prefix directly to the URI:

bash
aws s3 ls s3://my-bucket/logs/2026/ --recursive

That is often much faster and much easier to read than listing the whole bucket.

Add Summary and Human-Readable Sizes

For interactive inspection, these options are useful:

bash
aws s3 ls s3://my-bucket/backups/ --recursive --human-readable --summarize

What they add:

  • '--human-readable formats sizes as KiB, MiB, and GiB'
  • '--summarize prints total object count and total size at the end'

This is a practical command when you want a quick answer to questions such as "how much data is under this prefix" without writing a separate report script.

Use s3api list-objects-v2 for Structured Results

The aws s3 ls command is great for people reading the output. If you need structured data for filtering or integration, use aws s3api list-objects-v2 instead.

bash
1aws s3api list-objects-v2 \
2  --bucket my-bucket \
3  --prefix logs/2026/ \
4  --query 'Contents[].{Key: Key, Size: Size}' \
5  --output table

This has two advantages:

  • the output can be shaped with --query
  • the result can be emitted as JSON, table, or text

For example, JSON output is better for automation:

bash
1aws s3api list-objects-v2 \
2  --bucket my-bucket \
3  --prefix logs/2026/ \
4  --output json

If you are building shell pipelines or feeding another tool, s3api is usually the better interface.

Filter by Prefix Instead of Listing Everything

The biggest performance win is usually not a CLI option but a narrower prefix. Listing s3://my-bucket/ recursively on a large production bucket can be slow, expensive, and noisy.

Prefer targeted listings such as:

bash
aws s3 ls s3://my-bucket/incoming/ --recursive
aws s3 ls s3://my-bucket/archive/2025/12/ --recursive

That approach reduces clutter and avoids accidental full-bucket scans in automation.

Know the Difference Between Listing and Downloading

--recursive is also used with commands such as aws s3 cp and aws s3 rm, but on those commands it means something different: recurse through matching keys for copy or delete operations.

For listing, this is safe:

bash
aws s3 ls s3://my-bucket --recursive

For removal, this is dangerous:

bash
aws s3 rm s3://my-bucket/tmp/ --recursive

The flag is the same, but the effect is obviously not. Keep that distinction in mind when switching between commands.

Check Permissions and Region Problems First

If recursive listing fails, the issue is usually not recursion itself. It is more often one of these:

  • missing s3:ListBucket permission
  • wrong CLI profile
  • wrong bucket name
  • region or endpoint mismatch in specialized environments

A quick check of the active identity can save time:

bash
aws sts get-caller-identity

If that identity is not the one you expect, fix the profile or credentials before debugging the S3 command further.

Common Pitfalls

The biggest mistake is assuming that S3 folders are real directories rather than prefixes in object keys. Another common issue is using aws s3 ls --recursive for automation when s3api list-objects-v2 would provide cleaner machine-readable output. Developers also often run a full-bucket recursive listing when a narrow prefix would answer the question much faster. Finally, it is easy to get used to typing --recursive and forget that on commands such as rm or cp, that same flag can have destructive consequences.

Summary

  • Use aws s3 ls s3://bucket --recursive for a quick human-readable recursive listing.
  • Add a prefix to the S3 URI to narrow the result set and improve performance.
  • Use --human-readable and --summarize when you want interactive totals.
  • Switch to aws s3api list-objects-v2 when you need structured or queryable output.
  • Remember that S3 uses key prefixes, not real directories, even when the CLI output looks hierarchical.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.