Techalicious Academy / 2026-01-15-regex-therapy

(Visit our meetup for more great tutorials)

RENAME - BULK FILE OPERATIONS

The Power of rename

The Perl rename command transforms filenames using regex. One command can rename hundreds of files following a pattern.

Syntax:

rename [options] 's/PATTERN/REPLACEMENT/' files

Safety First - Dry Run

ALWAYS test with -n (dry run) first:

rename -n 's/old/new/' *.txt

This shows what WOULD happen without actually renaming anything. Only remove -n when you're sure it's right.

Basic Replacements

Replace text in filenames:

rename 's/photo/image/' *.jpg

Before: photo_001.jpg, photo_002.jpg
After:  image_001.jpg, image_002.jpg

The s/OLD/NEW/ syntax is Perl's substitution operator.

Case Conversion

Lowercase all filenames:

rename 'y/A-Z/a-z/' *

Uppercase all filenames:

rename 'y/a-z/A-Z/' *

The y/// is Perl's transliteration operator (character-by-character).

Removing Characters

Delete unwanted parts:

rename 's/_backup//' *.txt

Before: report_backup.txt
After:  report.txt

Remove spaces:

rename 's/ //g' *

The g flag means "global" - replace ALL occurrences, not just the first.

Replacing Spaces

Spaces in filenames are annoying. Replace with underscores:

rename 's/ /_/g' *

Before: file with spaces.txt
After:  file_with_spaces.txt

Or with dashes:

rename 's/ /-/g' *

Changing Extensions

Rename .jpeg to .jpg:

rename 's/\.jpeg$/.jpg/' *.jpeg

Important: escape the dot (\.) and anchor to end ($).

Without the anchor, "my.jpeg.photo.jpeg" would become "my.jpg.photo.jpeg" after the first replacement.

Batch change extensions:

rename 's/\.txt$/.md/' *.txt     # txt to markdown
rename 's/\.htm$/.html/' *.htm   # normalize HTML extension

Adding Prefixes

Add a prefix to all files:

rename 's/^/prefix_/' *

Before: file.txt
After:  prefix_file.txt

The ^ means start of filename.

Adding Suffixes (Before Extension)

This is trickier. You need to insert before the extension:

rename 's/(\.\w+)$/_backup$1/' *

Before: report.txt
After:  report_backup.txt

We'll explain capture groups in the next section.

Removing Prefixes

Remove IMG_ prefix from camera files:

rename 's/^IMG_//' IMG_*

Before: IMG_2024_06_15.png
After:  2024_06_15.png

Numbering Files

Sequential numbering is a bit more complex:

# First, let's use a counter
rename 's/^/sprintf("%03d_", ++$::count)/e' *

The /e flag evaluates Perl code in the replacement.

Before: apple.txt, banana.txt, cherry.txt
After:  001_apple.txt, 002_banana.txt, 003_cherry.txt

The Global Flag

Without g, only the first match is replaced:

rename 's/_/-/' a_b_c.txt
Result: a-b_c.txt

With g, all matches are replaced:

rename 's/_/-/g' a_b_c.txt
Result: a-b-c.txt

Use g when you want to replace every occurrence.

The Case-Insensitive Flag

Match regardless of case:

rename 's/PHOTO/image/i' *

This matches PHOTO, Photo, photo, pHoTo, etc.

Quick Examples

Normalize camera files:

rename 's/^DSC_?/photo_/' DSC*

Clean up AI-generated filenames:

rename 's/^\d{13}_//' *.png   # Remove timestamp prefix

Add dates to files:

rename 's/^/2024-01-15_/' *.txt

Remove common junk:

rename 's/\s*\(copy\)//i' *      # Remove "(copy)"
rename 's/\s*-\s*Copy//i' *      # Remove "- Copy"
rename 's/_\d+(?=\.\w+$)//' *    # Remove trailing numbers

Pro Tips

1. Always use -n first. Always.

2. Test on a copy of your files if you're nervous.

3. Use single quotes around the pattern to prevent shell expansion.

4. If a pattern doesn't match, the file isn't renamed (no error).

5. Process files in stages. Simple patterns, one step at a time.