1 unstable release
Uses new Rust 2024
| 0.1.4 | Jan 3, 2026 |
|---|---|
| 0.1.3 |
|
| 0.1.2 |
|
| 0.1.1 |
|
| 0.1.0 |
|
#373 in Filesystem
89KB
1.5K
SLoC
frencli
A fast, powerful command-line batch file renaming tool inspired by the "Multi-Rename Tool" in Total Commander.
📋 Changelog - See what's new in each version
📖 Usage Example - Complete workflow demonstration
Features
- Safe by Default: Always shows a preview of changes before performing them.
- Powerful Patterns: Support for filename, extension, counters, and metadata placeholders.
- Modifiers: Built-in support for lowercasing, uppercasing, title casing, and regex replacement.
- Undo Facility: Easily reverse your last batch of changes if you make a mistake.
- Collision Protection: Skips existing target files by default.
- Multi-Subcommand Support: Subcommands can be specified in any order for easier editing.
Installation
Via Cargo (Recommended)
cargo install frencli
From Source
git clone https://github.com/byezy/frencli.git
cd frencli
cargo build --release
cp ./target/release/fren ~/.local/bin/
Usage
frencli <SUBCOMMAND> [OPTIONS]
Subcommands
list: List files matching patternsrename: Generate a preview from a patternvalidate: Validate a rename patternapply: Apply rename operations (performs the rename)template: Template operations (listoruse)undo: Undo operations (checkorapply)audit: View audit log entries
Subcommand Order Flexibility
Subcommands can be specified in any order - the execution order is determined internally based on logical dependencies. This design makes it much easier to edit command lines, especially when working with different file sets.
Tip: If you are going to run a rename pattern multiple times on different file sets, place list at the end of your command for easier editing.
# Easy to edit - just change the patterns at the end
frencli rename "%N_backup.%E" apply --yes list /some/path/*.txt
# Same command, different files - just edit the end
frencli rename "%N_backup.%E" apply --yes list /some/other/*.jpg
All of these are equivalent:
frencli list *.txt rename "%N.%E" applyfrencli rename "%N.%E" list *.txt applyfrencli apply rename "%N.%E" list *.txt
The internal execution order is always: list → rename/template --use → validate → apply
Examples
List files:
# List files (shows just filenames)
frencli list "*.txt"
# List with full paths
frencli list "*.txt" --fullpath
# List recursively
frencli list "*.txt" --recursive
Rename files:
# Preview a rename
frencli list "*.jpg" rename "Vacation_%C3.%E"
# Apply the rename
frencli list "*.jpg" rename "Vacation_%C3.%E" apply --yes
# Use a template
frencli list "*.jpg" template --use photo-date apply --yes
Renaming Patterns
Patterns use the % character as a prefix for tokens. All tokens are case-insensitive (e.g., %N is the same as %n).
Placeholders
| Token | Description | Example (file.txt) |
|---|---|---|
%N |
Filename without extension | file |
%E |
Extension without the dot | txt |
%F |
Full filename (name + extension) | file.txt |
%C |
Counter (starts at 1) | 1, 2, ... |
%C3 |
Counter with padding (3 digits) | 001, 002, ... |
%P |
Immediate parent directory name | Documents |
%P1-3 |
Substring of parent directory | Doc |
%D |
Current date (YYYY-MM-DD) | 2025-12-18 |
%H |
Current time (HH-MM-SS) | 14-30-05 |
%FD |
File modification date | 2025-12-10 |
%FH |
File modification time | 09-15-00 |
Substring Selection
You can extract parts of the name or extension using start-end indices (1-indexed). Use a double hyphen -- to count from the end.
%N1-3: Chars 1 to 3 of the name.%N5-: Chars from index 5 to the end of the name.%N-5: Chars from the beginning up to index 5.%N--3: The name minus the last 3 characters (shorthand for from beginning to 3rd from end).%N3--4: Chars starting from index 3 up to the 4th character from the end.%E1-2: Chars 1 to 2 of the extension.
Modifiers
Modifiers apply makeations to the filename. Order matters! Modifiers are processed left-to-right as they appear in the pattern, and they operate on the accumulated result at the point where they are encountered.
%L: Lowercase the entire accumulated result.%U: Uppercase the entire accumulated result.%T: Title case the entire accumulated result (capitalizes after spaces, dots, dashes, underscores).%M: Trim leading and trailing whitespace from the accumulated result.%R/old/new: Replace occurrences ofoldwithnewin the accumulated result. Supports multiple delimiters:/,|,:,,,@.%X/pattern/new: Regex replacement in the accumulated result. Supports capturing groups and standard regex syntax.
How Modifiers Work
Pattern processing happens in two phases:
- Placeholder Expansion: Placeholders like
%N,%E,%Care replaced with their values - Modifier Application: Modifiers like
%L,%U,%Rare applied to the accumulated result
Key Rule: When a modifier is encountered, it applies to everything accumulated so far in the result string, not just what comes after it.
Example: Modifier Before Placeholder
# Pattern: %L%N.%E
# File: Photo_001.JPG
# Result: photo_001.jpg
%Lsets lowercase mode%Nadds "Photo_001" → becomes "photo_001" (lowercased immediately).adds literal dot%Eadds "JPG" → becomes "jpg" (still in lowercase mode)
Example: Modifier After Placeholder
# Pattern: %N%L.%E
# File: Photo_001.JPG
# Result: photo_001.jpg
%Nadds "Photo_001" (unchanged initially)%Lapplies lowercase to accumulated result → "Photo_001" becomes "photo_001".adds literal dot%Eadds "JPG" → becomes "jpg" (lowercase mode continues)
Note: Both examples produce the same result because %L affects everything after it. When placed before %N, it lowercases as text is added. When placed after %N, it lowercases the accumulated result.
Example: Order Matters - Multiple Modifiers
# Pattern: %U%N%L.%E
# File: photo_001.jpg
# Result: photo_001.jpg
%Usets uppercase mode%Nadds "photo_001" → becomes "PHOTO_001"%Lapplies lowercase to accumulated result → "PHOTO_001" becomes "photo_001".adds literal dot%Eadds "jpg" (lowercase mode continues)
Compare with: %L%N%U.%E would produce PHOTO_001.JPG (lowercase first, then uppercase) - different result!
Pattern Examples
Simple Case Modification
fren list "*.JPG" make "%L%N.%U%E" rename --yes
Organizing by Parent Folder
fren list "*" make "%P_%C2_%N.%E" rename --yes
Title Casing
fren list "*.mp3" make "%T%N.%E" rename --yes
Replacement
fren list "*.txt" make "%R/_/-%N.%E" rename --yes
Safety
frencli will never overwrite a file unless you explicitly provide the --overwrite flag. If a target filename already exists, frencli will print a warning and skip that specific file during execution.
Undo
The undo subcommand allows you to reverse the very last batch of renames performed in the current directory. It uses a hidden .fren_history.json file to keep track of changes.
# Check what can be undone
fren undo --check
# Apply undo
fren undo --apply
# Apply undo without confirmation
fren undo --apply --yes
If any of the files involved in the undo have been moved, deleted, or replaced by another process since the rename, frencli will notify you and skip reversing those specific files to prevent data loss.
License
This project is licensed under the MIT License.
Dependencies
~6.5–10MB
~168K SLoC