The Perils of Bulk Renaming in Linux Environments
System administrators, web developers, and data engineers frequently encounter directories containing hundreds or thousands of irregularly named files—such as digital camera dumps (IMG_0023.JPG), timestamped server backups, or files cluttered with unwanted whitespaces, brackets, and uppercase extensions. In standard Unix environments, resolving these naming inconsistencies traditionally requires complex Bash for loops paired with sed, or legacy Perl utilities like rename.
However, running custom shell loops without safety guards introduces severe risks: accidental file overwrites, unhandled whitespace collisions, and irreversible directory reorganisations. To solve these friction points with speed and mathematical safety, developer Roman Harlamov created rnr (an acronym for Rename Regex), a command-line tool implemented in Rust that provides safe, high-speed, and reversible batch file renaming powered by regular expressions.
Why rnr Excels Over Traditional Renaming Tools
rnr distinguishes itself from standard terminal utilities through several purpose-built architectural features:
- Default Dry-Run Mode: When you invoke rnr, it never alters files on disk by default. Instead, it prints a colour-coded preview table showing exact before-and-after paths. Changes are written to the filesystem only when you explicitly pass the
-f(or--force) execution flag. - Conflict Collision Detection: Before renaming a single file, rnr pre-computes the entire target set. If two disparate source files would produce the same destination filename, or if a destination file already exists, rnr aborts immediately, preventing data loss.
- Reversible History and Undo Engine: When execution occurs, rnr automatically records a temporary transaction log or outputs an undo script (via
-u/--dump-undo), allowing instantaneous recovery if a regex substitution behaves unexpectedly. - Recursive Directory Traversal: Traverses nested subtrees with parallel multithreaded directory walking, effortlessly processing hundreds of thousands of files in milliseconds.
How to Install rnr Across Linux Distributions
Because rnr is engineered in Rust, it can be deployed via Cargo, precompiled release binaries, or native package managers.
Method 1: Installing via Cargo (Universal)
If you maintain a standard Rust development environment on Ubuntu, Debian, Fedora, or openSUSE:
# Install Cargo and compiler tools if needed
sudo apt update && sudo apt install -y cargo build-essential
# Compile and install rnr into ~/.cargo/bin
cargo install rnr
Ensure that Cargo’s binary path is present in your active environment:
echo 'export PATH="$HOME/.cargo/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
Method 2: Installing on Arch Linux via AUR
Arch Linux users can install rnr directly from the AUR using yay or paru:
yay -S rnr
Method 3: Direct Precompiled Binary Deployment
To deploy the standalone precompiled binary directly from GitHub releases:
curl -sL https://github.com/ダム/rnr/releases/latest/download/rnr-linux-x86_64.tar.gz -o rnr.tar.gz
tar -xzf rnr.tar.gz
sudo install -m 755 rnr /usr/local/bin/rnr
rm -rf rnr.tar.gz rnr
Core Command Syntax and Operational Flags
The standard syntax for rnr requires the match pattern, the replacement string, and the target files or directories:
rnr [FLAGS] [OPTIONS] <EXPRESSION> <REPLACEMENT> [PATH]...
| Flag | Alternative | Functional Description |
|---|---|---|
-f |
--force |
Executes actual disk writes; without this flag, rnr runs strictly in dry-run simulation mode. |
-r |
--recursive |
Recursively descends into nested subdirectories to locate and rename matching files. |
-d |
--include-dirs |
Includes directory names in the renaming scope alongside standard regular files. |
-D |
--dirs-only |
Restricts renaming operations exclusively to directories, ignoring standard files. |
-s |
--silent |
Suppresses output reporting, ideal for silent background scripts and automation hooks. |
-u |
--dump-undo |
Generates a dedicated Bash undo script capable of rolling back the renaming operation. |
Practical Real-World Batch Renaming Scenarios
1. Normalising Spaces and Capital Letters to Snake_Case
Filenames containing whitespace or mixed capitalization disrupt command-line scripts and web servers. To replace all spaces with underscores across a directory while previewing changes:
# Safe dry-run inspection
rnr "\s+" "_" *.jpg
# Execute changes to disk
rnr -f "\s+" "_" *.jpg
2. Sanitising and Converting File Extensions to Lowercase
To standardise legacy uppercase camera extensions (e.g., converting .JPEG or .JPG to lowercase .jpg):
rnr -f "\.JPG$" ".jpg" ./media/
3. Renaming Date Formats Using Regex Capture Groups
Suppose you have hundreds of financial reports formatted as DD-MM-YYYY_report.pdf, but your archive requires ISO 8601 formatting (YYYY-MM-DD_report.pdf). Leverage regex capture groups:
# Capture day, month, and year groups
rnr -f '^(\d{2})-(\d{2})-(\d{4})_(.*\.pdf)$' '$3-$2-$1_$4' .
4. Stripping Leading Tracking Numbers or Prefix Tags
To strip unneeded numeric prefixes (e.g., transforming 01 - Track Title.flac into Track Title.flac):
rnr -f '^\d+\s*-\s*' '' ./music/
Creating and Executing an Undo Rollback Script
Before executing high-risk bulk renames across critical production volumes, always instruct rnr to dump an undo script:
rnr -f -u undo_rename.sh 'old_pattern' 'new_pattern' /var/data/
If you discover that an incorrect regex was passed, restore the original filenames immediately:
bash undo_rename.sh
The undo script executes surgical mv operations in reverse order, effortlessly restoring the initial directory state without manual recovery efforts.