| Crates.io | fren-core |
| lib.rs | fren-core |
| version | 0.2.1 |
| created_at | 2025-12-18 07:15:26.850106+00 |
| updated_at | 2025-12-19 12:37:44.076629+00 |
| description | Core renaming engine for fren |
| homepage | https://github.com/byezy/fren |
| repository | https://github.com/byezy/fren |
| max_upload_size | |
| id | 1991875 |
| size | 169,316 |
The core renaming engine behind the fren suite. This library provides a robust, safe, and powerful DSL for batch file renaming, suitable for use in CLI tools, GUI applications, or web backends.
📋 Changelog - See what's new in each version
** glob patterns, preserving full directory structure%N, %E, %C, etc.) and modifiers (%L, %U, %R, %X)%N%L.%E work correctlyPatterns are processed in two phases:
%N, %E, %C are replaced with their values%L, %U, %R are applied left-to-right to the accumulated resultWhen a modifier is encountered, it operates on everything accumulated so far in the result string. This means:
%L%N.%E and %N%L.%E both work (modifier before or after placeholder)%U%N%L.%E will uppercase then lowercase the nameAdd this to your Cargo.toml:
[dependencies]
fren-core = "0.2.1"
tokio = { version = "1", features = ["fs", "io-util", "macros", "rt-multi-thread"] }
futures = "0.3"
Note: fren-core requires a tokio runtime. Make sure your application uses #[tokio::main] or provides a tokio runtime.
use fren_core::RenamingEngine;
use fren_core::find_matching_files_recursive;
use std::path::PathBuf;
#[tokio::main]
async fn main() {
let engine = RenamingEngine;
// Find files recursively
let files = find_matching_files_recursive("**/*.jpg", true)
.await
.unwrap();
// Generate a preview plan (async)
let preview = engine.generate_preview(&files, "%L%N_v2.%E")
.await
.unwrap();
for rename in preview.renames {
// old_path and new_path contain full paths, preserving directory structure
println!("{} -> {}", rename.old_path.display(), rename.new_path.display());
// new_name contains just the filename
println!(" New filename: {}", rename.new_name);
}
// Validate renames (async)
let validation = engine.validate(&preview.renames, false).await.unwrap();
if !validation.issues.is_empty() {
for issue in validation.issues {
eprintln!("Validation issue: {:?}", issue);
}
}
}
When generate_preview processes files (including recursively found files), it preserves the full directory structure:
old_path: Full original file path (e.g., /path/to/docs/document.pdf)new_path: Full new file path in the same directory (e.g., /path/to/docs/document_v2.pdf)new_name: Just the filename portion (e.g., document_v2.pdf)Files found recursively maintain their directory structure - a file in subdir/nested/file.txt will be renamed to subdir/nested/<new_name>, not moved to the root directory.
All operations in fren-core are asynchronous. You'll need a Tokio runtime to use the library:
#[tokio::main] for standalone applicationstokio::spawn or tokio::task::spawn_blocking in existing async contextsThis project is licensed under the MIT License.