Documentation

Learn RenForge by example.

Everything the app can do, with before & after file names you can copy. The same guide is built into the app: press F1 or click Help.

Your first rename

Goal: turn camera names into holiday names. The folder contains IMG_0042.JPG, IMG_0043.JPG, IMG_0044.JPG and a few .txt notes you want to leave alone.

  1. Click Select Folder… (or drag the folder onto the window).
  2. Under 1. Filters, click + Add filter, choose extension and type jpg. Only the photos remain in the list.
  3. Under 2. Rename steps, click + Add rename step. Choose Replace text: find IMG_, replace with Holiday_.
  4. Add a second step, Change case → lowercase extension.
  5. Check the preview. Untick any file you want to skip.
  6. Click Apply with Dry run ticked (the default). RenForge only reports what it would do.
  7. Happy? Untick Dry run and click Apply again. Keep Create undo log ticked.
Result
IMG_0042.JPG
→
Holiday_0042.jpg
IMG_0043.JPG
→
Holiday_0043.jpg
IMG_0044.JPG
→
Holiday_0044.jpg
Tip: try RenForge on a copy of a few files first. With Dry run on, nothing is ever changed.

The window

AreaWhat it does
Top barSelect Folder…, Recent… (last 5 folders), Refresh, Include subfolders, A− / A+ (text size), Auto / Light / Dark (colours), Help, About. You can also drag a folder onto the window. Window size, text size and colour mode are remembered.
1. FiltersChoose which files are affected (optional).
2. Rename stepsDescribe how names change. Each step has a checkbox (on/off), ▲ ▼ (reorder), ✕ (remove) and Presets…
3. OptionsAlso rename related files (sidecars, RAW+JPEG pairs); Edit file types… opens the list of extensions.
Preview (right)Original name next to the new name (the changed part is highlighted), a checkbox per file and ⚠ warnings. Order sorts the list; drag the divider in the column header to resize the columns. A summary line shows what will rename, what is invalid, duplicated or taken, and what stays unchanged; click a problem count to see just those files.
Bottom barDry run, Create undo log, Undo… and Apply.

Filters

Filters decide which files appear in the preview. With no filters every file in the folder is included. A filter with an empty value is ignored, and only the file name is checked, never the folder path.

ModeMatches when…Example value
containsthe name contains the textholiday
starts withthe name begins with the textIMG_
ends withthe name ends with the text (extension included)_edit.jpg
extensionthe extension equals the valuepng, .png, tar.gz
regexthe name matches a regular expression^IMG_\d{4}\.jpe?g$
  • Match ALL (AND): a file must satisfy every filter. Match ANY (OR): at least one.
  • Case sensitive is off by default, so PNG and png are the same.
  • An invalid regular expression is flagged in red and matches nothing.
Example: only photos that start with IMG_

Filters: starts with IMG_ AND extension jpg

IMG_0042.jpg
✓
listed
IMG_0042.png
✗
hidden (wrong extension)
holiday.jpg
✗
hidden (does not start with IMG_)

Selecting & sorting

  • Every matching file has a checkbox. Untick files to leave them alone. Select All / Deselect All act on the files currently listed.
  • Show: All / Changed / Problems narrows the preview. Changed hides unchanged and unticked files; Problems shows only files with a ⚠ (invalid name, duplicate name, or a name already taken by a file that is not being renamed). The buttons show live counts, and Problems turns amber when something needs fixing.
  • The header shows the counts, for example 42 matches · 38 selected · 100 total files.
  • The list scrolls smoothly even with tens of thousands of files, and folders are scanned in the background.
  • Order sorts by name (natural: img2 before img10), date (capture date, else modified) or size. Numbering follows the order shown.
  • Rows marked (unchanged) already have the target name and are skipped.

Rename steps

Steps form a pipeline: the result of step 1 is the input of step 2, and so on. Use ▲ ▼ to reorder, the checkbox to switch a step off without deleting it, and ✕ to remove it. Order matters: Prepend then Change case is not the same as the reverse. Each step shows an Example line (the first selected file, before → after that step), and the arrow button collapses a step to one line.

Replace text & Remove text

Replace swaps every occurrence of A for B (leave B empty to delete). Remove deletes the text. Matching is case sensitive.

Replace A = _ B = (a space)
my_holiday_photo.jpg
→
my holiday photo.jpg
Remove text = IMG_
IMG_0042.jpg
→
0042.jpg

Prepend, Append & Insert before extension

Prepend 2024_
beach.jpg
→
2024_beach.jpg
Insert before extension _final (Append does the same)
cut.mp4
→
cut_final.mp4
backup.tar.gz
→
backup_final.tar.gz

Change extension

With or without the dot; empty removes the extension. .tar.gz, .tar.bz2, .tar.xz and .tar.zst count as one extension, and dotfiles such as .bashrc have none.

Change extension png
a.jpeg
→
a.png

Change case

Changes the case of the name; the extension is untouched unless you pick an extension option.

OptionBeforeAfter
lowercaseMy FILE.TXTmy file.TXT
UPPERCASEmy file.txtMY FILE.txt
Title Casethe don't STOP-me_now.mp3The Don't Stop-Me_Now.mp3
Sentence casehELLO wORLD.txtHello world.txt
snake_caseMy Great-Photo (final).JPGmy_great_photo_final.JPG
kebab-caseMy Great Photo.jpgmy-great-photo.jpg
lowercase extensionA.JPGA.jpg
UPPERCASE extensiona.jpga.JPG

Clean up

OptionBeforeAfter
Collapse repeated spacesa   b  c.txta b c.txt
Trim spaces around name  a b  .txta b.txt
Remove accentsCafé Crème.txtCafe Creme.txt
Dots and underscores to spacesMy.Cool_Song.mp3My Cool Song.mp3
Remove copy markersreport (2).pdf, report - Copy.pdf, Copy of report.pdfreport.pdf
Note: RenForge never trims spaces for you. A result that starts or ends with a space is flagged as invalid so you notice it. A red message under a step means a setting is wrong (for example an invalid regex); the preview skips that step until it is fixed.

Numbering

Number files gives every selected file a sequence number, in the order shown. Untick a file and the others are renumbered.

  • A (template): {n} = number, {n:3} = padded to 3 digits, {name} = original name without extension. The extension is kept automatically. Empty means {name}_{n:3}.
  • B (start, step): 1 starts at 1; 100,10 gives 100, 110, 120…
  • Tick Restart numbering in each folder when Include subfolders is on and each folder should start again.
Template Trip_{n:4} start 1
DSC_9981.jpg
→
Trip_0001.jpg
DSC_9985.jpg
→
Trip_0002.jpg
DSC_9990.jpg
→
Trip_0003.jpg
Template {n:2}-{name} start,step 10,5
beach.jpg
→
10-beach.jpg
forest.jpg
→
15-forest.jpg

Regex

A regular expression (regex) describes a pattern. In Regex replace, A is the pattern and B the replacement; $1, $2… insert the parts captured by brackets. The whole name, extension included, is matched. Start the pattern with (?i) to ignore case. The regex filter uses the same syntax and follows the Case sensitive box. The syntax is Go's RE2.

Pattern (A)Replacement (B)Before → after
IMG_(\d+)Holiday-$1IMG_0042.jpg → Holiday-0042.jpg
\s+_my  file.txt → my_file.txt
^(\d{4})-(\d{2})-(\d{2})$3.$2.$12024-06-01_x.jpg → 01.06.2024_x.jpg
\[.*?\](empty)a [1080p] b.mp4 → a b.mp4
(?i)\.jpe?g$.jpgpic.JPEG → pic.jpg

Tip: follow a regex that leaves double spaces with Clean up → Collapse repeated spaces.

Photos & EXIF dates

Rename from template builds the whole name from tokens. The capture date is read from the EXIF data inside the picture (JPEG and TIFF-based RAW formats such as CR2, NEF, DNG, ARW). Files without EXIF (and HEIC/CR3, whose metadata RenForge cannot read yet) use their modified date, so the template still works. EXIF is only read, never written.

TokenMeaning
{date} / {date:YYYY-MM-DD_HHmmss}capture date; format letters YYYY YY MM DD HH mm ss (default YYYY-MM-DD)
{modified} / {modified:YYYY}file modification date, same format letters
{n} / {n:3}sequence number, padded to 3 digits
{name}original name without extension
{parent}name of the folder the file is in
{camera} {make} {lens} {iso}from EXIF (shows unknown when missing)
Template {date:YYYY-MM-DD}_{n:3} order Date, oldest first

Photos taken on 1 June 2024, in this order:

IMG_4021.CR2
→
2024-06-01_001.CR2
IMG_4020.CR2
→
2024-06-01_002.CR2
Template {date:YYYYMMDD_HHmmss}_{camera}
IMG_4021.CR2
→
20240601_140509_EOS R5.CR2
Tip: keep {n} in the template when several photos can share a second (bursts, two cameras). RenForge warns when it is missing. Reading dates for a large folder happens in the background; a progress bar appears above the list and the preview fills in when it is done.

Image sequences

Shift frame numbers adds an offset to the number at the end of the name. A is the offset (+1000, -1), B an optional padding (empty keeps the current width). Only the last number changes.

Offset +1000
shot.0001.exr
→
shot.1001.exr
shot.0240.exr
→
shot.1240.exr
Offset +1 (each file takes the name of the next)
shot_0099.exr
→
shot_0100.exr
Offset -41
shot.0042.exr
→
shot.0001.exr

Shifts such as +1 are fine: RenForge moves all files out of the way first. If a file that is not part of the batch occupies a target, the whole affected chain is skipped and reported, so nothing is half-shifted. Undo restores such shifts too. A frame that would become negative is left unchanged.

Presets

Click Presets… (next to + Add rename step):

  • Load a built-in or your own preset. Loading replaces the current filters and steps.
  • Save current as… stores your filters, steps and match options under a name (saving under an existing name asks before replacing it).
  • Delete removes your own presets; built-ins cannot be deleted.
Built-in presetExample
Clean up downloadsMy.Cool_Song (1).MP3 → My Cool Song.MP3
Lowercase names and extensionsHOLIDAY.JPG → holiday.jpg
kebab-case namesMy Great Photo.JPG → my-great-photo.jpg
Photos: Trip_0001DSC_9981.jpg → Trip_0001.jpg
Photos by dateIMG_4021.CR2 → 2024-06-01_001.CR2
Photos by date and timeIMG_4021.CR2 → 20240601_140509_01.CR2
Image sequence: start at frame 1001shot.0001.exr → shot.1001.exr
Add number suffixbeach.jpg → beach_001.jpg

Your presets are plain JSON files in renforge/presets inside your user configuration folder (macOS ~/Library/Application Support, Windows %AppData%, Linux ~/.config). Copy them to another computer to share them.

Dry run & safety checks

When you click Apply, RenForge checks every selected file and skips any that would cause trouble. Dry run is ticked by default and changes nothing.

ProblemMeaning
Invalid nameEmpty; contains \ / : * ? " < > | or control characters; starts with a space; ends with a space or dot; longer than 255 bytes; or a reserved Windows name (CON, NUL, COM1…). These rules keep files usable on every system.
ConflictTwo selected files in the same folder would get the same name.
Target existsA different file that is not being renamed already has the new name. (A target held by a file that is itself being renamed away, as in +1 frame shifts or swaps, is fine.)

Allowed: swapping names (a.txt ↔ b.txt), and changing only the letter case (IMG.jpg → img.jpg), even on Windows and macOS where names are case-insensitive.

How it renames: each file first moves to a temporary name (.renforge_tmp_…), then to its final name. Existing files are never overwritten. If a file cannot be renamed it goes back to its old name; in the very unlikely case that fails too, the result dialog lists the file left under its temporary name.

Undo

Keep Create undo log (CSV) ticked. RenForge asks where to save the log (it suggests the folder you are working in) and writes it after the rename, so it records what really happened.

  1. Click Undo…. RenForge offers the most recent log, or lets you choose any log file.
  2. It shows how many renames can be restored and lists any it cannot: not found (moved or deleted since) or in use again (another file now has the original name).
  3. Confirm, and the original names come back.

A log from a dry run contains no completed renames, so there is nothing to undo. The CSV has the columns old_path, new_path, old_name, new_name, status, reason and opens in any spreadsheet.

Recipes

I want to…FiltersSteps
Replace underscores with spaces–Replace _ → (space)
Remove “ (1)” copiescontains (1)Clean up → Remove copy markers
Add a date prefix–Prepend 2024-06-01_
Mark finalsextension mp4Insert before extension _final
Convert .jpeg to .jpgextension jpegChange extension jpg
Strip a download-site tagcontains [site.com]Remove text [site.com]
Lower-case every extension–Change case → lowercase extension
Name photos by dateextension jpg (order: Date, oldest first)Rename from template {date:YYYY-MM-DD}_{n:3}
Keep RAW + XMP + JPG togetherextension cr2, option related files onany step, for example Prepend Trip_
Start a render sequence at 1001extension exrShift frame numbers +1000
kebab-case everything–Change case → kebab-case

Troubleshooting

ProblemWhat to do
The preview is emptyCheck that a folder is selected and the filters are not too strict. Tick Include subfolders if the files are inside sub-folders.
⚠ conflictTwo files would get the same name. Make the name more unique (add {n}) or untick a file.
⚠ target existsA file with the new name is already in that folder. Rename or move it first.
Files changed in another programClick Refresh.
“Cannot undo”The files in the log were moved, deleted or renamed again. Nothing was changed.
A .renforge_tmp_… file is leftOnly after a failed rename that also could not be restored. The result dialog names the file; rename it by hand (the undo log has its original name).
macOS: “cannot be opened”If the build is not notarized, run xattr -dr com.apple.quarantine renforge.app.
Windows: SmartScreen warningWindows builds are not code-signed yet: More info → Run anyway.

Still stuck? Report a bug with your OS, the build you used, and the steps to reproduce.

Build from source

Prerequisites

  • Go: the version listed in go.mod (or newer) from go.dev/dl.
  • A C compiler and graphics libraries, because the UI toolkit (Fyne) needs them:
    • macOS: Xcode command line tools: xcode-select --install
    • Windows: MinGW-w64 gcc, for example via MSYS2
    • Linux (Debian/Ubuntu): sudo apt install gcc pkg-config libgl1-mesa-dev xorg-dev libasound2-dev

Run, test and build

# get the code
$ git clone https://github.com/blackarck/renforge.git
$ cd renforge

# run the app
$ go run .

# run the tests (the rename engine is UI-free and well covered)
$ go test ./...

# build a plain binary
$ go build -o renforge .

A plain go build has no application icon, and on Windows it opens a console window. For a proper app, use the Fyne packager; it reads FyneApp.toml and icon.png:

$ go install fyne.io/tools/cmd/fyne@latest
$ fyne package -os darwin     # renforge.app
$ fyne package -os windows    # renforge.exe, no console window
$ fyne package -os linux      # renforge.tar.xz

Project layout

PathContains
renforge.go, rows.go, presets.go, help.go, icon.goThe Fyne user interface, in-app help and window icon
internal/renameRename steps, name validation, plan building, sidecars, two-phase apply
internal/filterFilter rules
internal/undoUndo log (CSV) reading, writing and reverting
internal/metaCached file size, dates and EXIF
internal/presetSaved and built-in presets
docs/User guide, release and signing notes

Want to help? Read CONTRIBUTING.md or jump to how to support the project.