How to bulk-rename S3 files by pattern

TL;DR

S3 has no batch-rename call — renaming is always copy-then-delete, one key at a time, whether you script it or click a button. S3 Viewer's Bulk rename… runs a pattern (find/replace, add a prefix or suffix, change the extension, or lowercase every key) over a selection or a whole folder, shows you every resulting old-to-new name before touching anything, and blocks the run if two files would collide or a target key already exists. Then it executes the same per-object rename S3 Viewer already uses everywhere else, with progress and per-file failures.

Steps

Step-by-step.

  1. 01

    In S3 Viewer: select files (or a folder) and choose Bulk rename…

    Select the rows you want, or open a folder's ⋮ menu, and choose Bulk rename…. Pick an operation — find/replace (with a case-sensitive toggle and a choice between the first match and all occurrences), add a prefix, add a suffix before the extension, change the extension, or lowercase every name.
  2. 02

    Review the preview before running anything

    The dialog shows old → new for up to the first 200 changed names, with the total count above it; names the pattern doesn't change are skipped rather than listed. If two files would land on the same new key, or a target key already exists in the bucket, those rows are flagged and the run is blocked until you adjust the pattern.
  3. 03

    AWS CLI: script it yourself

    There's no batch-rename flag on aws s3 — loop over aws s3 ls output (or aws s3api list-objects-v2 for exact keys) and run aws s3 mv per file, building the new key with sed or your shell's own string substitution.
    aws s3 ls s3://my-bucket/exports/ | awk '{print $4}' | while read -r key; do
      new="${key/draft-/final-}"
      [ "$key" = "$new" ] && continue
      aws s3 mv "s3://my-bucket/exports/$key" "s3://my-bucket/exports/$new"
    done
  4. 04

    SDK: compute every new key, then copy + delete each one

    A script version of the same idea: list the keys, transform each one with your pattern, skip the ones that don't change, and run copyObject + deleteObject for the rest — checking that the copy actually succeeded before deleting the source, the same way any rename should.
    for (const key of keys) {
      const newKey = key.replace(/^draft-/, 'final-');
      if (newKey === key) continue;
      await s3.copyObject({ Bucket, CopySource: `${Bucket}/${key}`, Key: newKey });
      await s3.deleteObject({ Bucket, Key: key });
    }
  5. 05

    It's still N renames, not one atomic operation

    Bulk rename runs the same per-object copy-then-delete as a single rename, just for every matched key — it isn't a single S3 call and isn't atomic across the batch. S3 Viewer reports progress and per-file failures rather than an all-or-nothing result, and the run is resumable if you stop partway through: files already renamed aren't retried.
Under the hood

What's actually happening.

A “bulk rename” is never one operation on S3 — it's the same CopyObject + DeleteObject pair a single rename uses, repeated once per key that actually changes. S3 Viewer's part is entirely client-side pattern matching: given the operation you picked, it computes every new key locally, drops the ones that are identical to the original, and only then talks to the API.


Before running anything, it checks the computed keys for internal collisions (two sources landing on the same target) and for collisions with what's already in the bucket, using the same chunked existence check the upload flow uses for duplicate detection. Either kind of collision blocks the run — there is no “last write wins” fallback.


Execution reuses the existing per-object rename path (files) or the same relist-then-move chunking folder rename already does (folders), at bounded concurrency, with progress and per-key failures surfaced rather than a single pass/fail result — and it's resumable, since a file already renamed is never retried on a second pass.

FAQ

Common questions.

Can I rename multiple S3 files at once?

Not with one API call — S3 has no batch rename, only per-object copy and delete. S3 Viewer's Bulk rename… applies a pattern (find/replace, add a prefix or suffix, change the extension, or lowercase) across a selection or a folder, previews every resulting name, and then runs the same per-object rename for each matched file, with progress shown as it goes.

How do I find and replace text in S3 file names?

In S3 Viewer, Bulk rename… → Find/replace, with a case-sensitive toggle and a choice of replacing only the first match or every occurrence in each key. From a script, loop over the keys yourself and apply a string replace before calling copyObject + deleteObject on the ones that actually change.

What happens if a bulk rename would create duplicate file names?

S3 Viewer checks the computed target keys against each other and against what's already in the bucket (via a batched existence check) before the run starts. Any collision — two source files mapping to the same new key, or a new key that's already occupied — is flagged in the preview table and blocks Run until you change the pattern.

Does bulk rename work on a whole folder in S3?

Yes — choosing Bulk rename… from a folder's menu lists every key under that prefix the same way folder delete and folder move do, applies the pattern to each, and previews and runs the result the same as a selection.

Is bulk renaming S3 files reversible?

No more than a single rename is: each file is copied to its new key and the original deleted. There's no S3 undo. Review the preview table carefully, and note the pattern down (or keep the S3 Viewer activity log if your server has it enabled) if you might need to reverse it.

Does bulk rename cost more than a normal rename?

The same per-object cost as N individual renames — one CopyObject and one DeleteObject request per file that actually changes. There's no batch discount, since it's still N separate operations under the hood; files the pattern doesn't change aren't touched at all.
Use S3 Viewer for this

Skip the CLI. Try it in the browser.

S3 Viewer turns the steps above into a single click. Open source, self-hostable, free.