fnorm
A Rust-based command-line bulk renaming tool designed to normalize file names across directories.
Supports recursive walking, dynamic rename templates, image dimension extraction, configuration via .fnorm.toml, dry-run safety, and collision handling.
Usage
[PATH]: Root directory to process. Defaults to the current directory (.).
Options
| Option | Description | Default |
|---|---|---|
--config <PATH> |
Use a specific config file for this run | None |
--global |
Use global indexing instead of per-directory | false |
--no-dry-run |
Actually perform renames | Enabled by default |
-h, --help |
Show help | - |
Behavior
Recursive Walking
- Uses
walkdirto traverse all subdirectories. - Processes only files (skips directories).
- Processing order is filesystem-dependent.
Indexing
By default, the {N} index resets for every subdirectory. If you run with the --global flag, {N} increments globally across the entire tree. CLI flags always override settings found inside .fnorm.toml.
Template Engine
Everything outside of curly braces {} is treated as a literal string.
Supported Placeholders
| Placeholder | Description |
|---|---|
{parent} |
Parent folder name (lowercase) |
{PARENT} |
Parent folder name (uppercase) |
{N} |
Incrementing index |
{ext} |
Original file extension (without dot) |
{width} |
Image width (empty for non-images) |
{height} |
Image height (empty for non-images) |
Template Examples
- Standard:
{parent}-{N}.{ext}Output:folder-1.txt,folder-2.txt - Prefix:
{N}-preview.{ext}Output:1-preview.png,2-preview.png - Image Aware:
{parent}-{N}_{width}x{height}.{ext}Image:photos-1_1920x1080.jpgText file:photos-2.txt(Separators_andxare cleaned up automatically).
Configuration
fnorm supports layered configuration with the following priority:
- Command line flag:
--config <path> - Local
.fnorm.tomlin the execution directory - Global
.fnorm.tomlin the executable directory - Built-in defaults
Example .fnorm.toml
= "{parent}-{N}.{ext}"
# Options: "per-directory" | "global"
= "per-directory"
# Characters removed when dimension placeholders are empty
= ["_", "-", " "]
Safety & Collisions
Dry Run (Default)
By default, fnorm does not rename files. It only prints the planned changes. To execute the renaming, you must explicitly use:
Collision Handling
fnorm will never overwrite existing files. If a name collision occurs (e.g., file.txt already exists), it automatically resolves the conflict by appending an incrementor:
file.txtfile-1.txtfile-2.txt
Example
Given this directory structure:
With the following template in .fnorm.toml:
= "{parent}-{N}_{width}x{height}.{ext}"
Running fnorm ./test/ results in this dry-run output:
./test/image1.jpg -> ./test/test-1_1920x1080.jpg
./test/image2.jpg -> ./test/test-2_1280x720.jpg
./test/file.txt -> ./test/test-3.txt
./test/folder1/testfile.txt -> ./test/folder1/folder1-1.txt
./test/folder2/picture.png -> ./test/folder2/folder2-1_800x600.png
Note: Non-image files automatically drop
{width}x{height}placeholders and their preceding separators.
Technical Details
- Image Detection: Uses the
imagecrate to extract metadata without a full decode, keeping the process fast. - Platform Support: Works on Windows, macOS, and Linux using native path separators and UTF-8 handling.
- Limitations: No parallel processing or exclusion filters are currently implemented (planned for future releases).
Installation
From Source
The binary will be located at target/release/fnorm.
License
This project is licensed under the MIT License.