← Notes

Regular expressions for renaming, without the jargon

Regular expressions look like line noise, but renaming files needs only about a dozen pieces of the language. Here they are in plain English, with the examples people actually need.

A regular expression is a way of describing the shape of some text rather than its exact contents. "Four digits, a dash, two digits." "Anything in square brackets." "The word final at the very end."

For renaming files, shape is what you usually need. You do not want to replace IMG_4821; you want to replace IMG_ followed by any number. That is a job for a regular expression, and you need very little of the language to do it.

The pieces you need

Ordinary characters match themselves. Report matches the text Report. Most letters and digits need no special treatment.

. means any single character. R.port matches Report, R2port or R-port — exactly one character in that position. It does not match Rapport, which has two.

\d means any digit. \d\d\d\d matches four digits in a row — a year, for example.

\s means any space, including tabs.

\w means a "word" character: letters, digits and underscore.

Quantifiers say how many:

  • + — one or more: \d+ is a number of any length.
  • * — zero or more.
  • ? — zero or one, making the thing before it optional.
  • {4} — exactly four: \d{4} is the same as \d\d\d\d.
  • {2,3} — two or three.

Square brackets are "one of these". [-_ ] matches a dash, an underscore or a space. [A-Z] matches one capital letter.

^ and $ pin to the start and end. ^draft matches only names that start with draft. final$ matches names that end with it.

Parentheses capture. Whatever matches inside ( ) is remembered, and you can put it back in the replacement as $1, $2 and so on, numbered from the left. (Some tools write this as \1.)

A backslash makes a special character ordinary. . means "any character"; \. means an actual full stop. The same goes for brackets, parentheses, +, ? and $.

That is the whole toolkit for most renaming.

Examples

Change a prefix, keep the number. Find IMG_(\d+) → Replace Holiday_$1 IMG_4821.jpg → Holiday_4821.jpg

Reorder a date to sort properly. Find (\d{2})\.(\d{2})\.(\d{4}) → Replace $3-$2-$1 Invoice 15.09.2026.pdf → Invoice 2026-09-15.pdf

Move a date from the end to the start. Find ^(.+) (\d{4}-\d{2}-\d{2})$ → Replace $2 $1 Board minutes 2026-09-15 → 2026-09-15 Board minutes

Remove anything in brackets. Find \s*\[[^\]]*\] → Replace with nothing Song [Remastered 2011] → Song

[^\]]* means "any characters that are not a closing bracket", which stops the match at the first ].

Pad a number to three digits. Regular expressions cannot count, so this takes two passes: first add zeros to one-digit numbers, then to two-digit ones. Or use a dedicated numbering rule, which is easier.

Collapse repeated separators. Find [-_ ]+ → Replace _ My - file__name → My_file_name

Two traps

Greedy matching. .* and .+ match as much as they possibly can. \[.*\] applied to A [x] B [y] matches [x] B [y] — from the first bracket to the last. Adding ? makes it lazy: \[.*?\] matches [x] and [y] separately. When a replacement removes more than you expected, greediness is the usual cause.

Forgetting the dot. .jpg as a pattern also matches Xjpg or _jpg, because . means any character. Write \.jpg when you mean the extension.

Test before you rename

Regular expressions are unforgiving, and a small mistake is applied to every file at once. Two habits:

  1. Try the pattern on a sample first. Online testers like regex101 show exactly what matches and what each group captures. Paste a few real filenames — not confidential ones — and experiment there.
  2. Preview every result before renaming, and sort the preview so unexpected ones stand out.

Also check which flavour of regular expressions your tool uses. The basics above work almost everywhere, but details such as $1 versus \1, or support for lazy *?, vary.

Where RenameDeck fits

RenameDeck is a batch renamer for Mac, and its Replace rule accepts literal text, wildcards or regular expressions, with capture groups available in the replacement. You choose whether a rule targets the name, the extension, the full name or the path — so a pattern aimed at names never touches extensions by accident.

The full list of proposed names appears before anything changes, is searchable, and flags invalid names and collisions. RenameDeck never overwrites an existing file. For padding and numbering, dedicated sequence, zero-pad and renumber rules avoid the two-pass trick. Rules stack into saved recipes, and journaled history supports undo.

It is sandboxed with no network entitlement, account, analytics or tracking, and requires macOS 14 or later.

Keep reading