Implement extra tags.

This commit is contained in:
Pedro de Oliveira 2023-05-07 23:20:33 +01:00
parent 713e4f9f7a
commit 3944583aef
2 changed files with 67 additions and 10 deletions

View File

@ -14,15 +14,37 @@ cargo install --git https://git.deadbsd.org/falso/rmv.git
To use `rmv`, you need to specify the path to the directory where the files to be renamed are located, a regular expression pattern to match against the filenames, and a replacement pattern for the matched filenames.
In the `--replacement` argument, you can use reference groups in the pattern by using `\1`, `\2`, etc. For example, if you have a pattern `"S(\d+)E(\d+)"`that matches `"S01E11"` and you want to replace it with `"Season 01 Episode 02"`, you can use the following replacement pattern: `"Season \1 Episode \2"`.
`rmv --path <PATH> --pattern <PATTERN> --replacement <REPLACEMENT>`
### `--path`
The `--path` argument specifies the path to the directory where the files to be renamed are located. This argument is required.
### `--pattern`
The `--pattern` argument specifies the regular expression pattern to match against the filenames. This argument is required.
You can use matching groups in the pattern to capture parts of the filename that you want to use in the replacement pattern. For example, the pattern `"S(\d+)E(\d+)"` will match on `"S01E23"` and capture `"01"` in group `1` and `"23"` in group `2`.
### `--replacement`
The `--replacement` argument specifies the replacement pattern for the matched filenames. This argument is required.
You can use reference groups in the pattern by using `\1`, `\2`, etc. to refer to the captured groups in the `--pattern` argument. For example, if you have a pattern `"S(\d+)E(\d+)"` that matches `"S01E11"` and you want to replace it with `"Season 01 Episode 02"`, you can use the following replacement pattern: `"Season \1 Episode \2"`.
You can also use the following special tags in the replacement pattern:
* `{full_name}` - file name with extension
* `{name}` - filename without extension
* `{ext}` - extension
Here is an example usage:
```shell
$ rmv --path /path/to/files --pattern "S(\d+)E(\d+).*\.(...)" --replacement "Season \1 Episode \2.\3" --wildcard "*.mkv"
$ rmv --path /path/to/files --pattern "S(\d+)E(\d+)" --replacement "Season \1 Episode \2.{ext}" --wildcard "*.mkv"
```
This will match all filenames in the directory that match the pattern `"S(\d+)E(\d+).*\.(...)"` and replace them with the pattern `"Season \1 Episode \2.\3"`. Only files with the `".mkv"` extension will be considered.
This will match all filenames in the directory that match the pattern `"S(\d+)E(\d+)"` and replace them with the pattern `"Season \1 Episode \2.{ext}"`. Only files with the `".mkv"` extension will be considered.
```shell
mv "Not Warez - S01E16 - HDTV-720p.mkv" "Season 01 Episode 16.mkv"
@ -43,11 +65,17 @@ Here are the available options:
-s, --pattern <PATTERN>
Regular expression pattern to match against the filenames in the directory.
The pattern should contain match groups (expressed in parentheses). Example: "S(\d+)E(\d+).*\.(...)"
The pattern should contain match groups (expressed in parentheses).
Example: "S(\d+)E(\d+).*\.(...)"
-r, --replacement <REPLACEMENT>
Replacement pattern for the matched filenames.
You can use `\1`, `\2`, etc. to reference the match groups in the pattern. Example: "Season \1 Episode \2.\3"
You can use `\1`, `\2`, etc. to reference the match groups in the pattern.
There are also the following tags available:
* {full_name} - file name with extension
* {name} - filename without extension
* {ext} - extension
Example: "Season \1 Episode \2.{ext}"
-w, --wildcard <WILDCARD>
Filename wildcard to filter the files to be renamed in the directory.

View File

@ -1,7 +1,7 @@
use clap::Parser;
use glob::glob;
use regex::Regex;
use std::path::PathBuf;
use std::path::{Path, PathBuf};
#[derive(Parser, Debug)]
#[command(author, version, about)]
@ -13,14 +13,24 @@ struct Args {
/// Regular expression pattern to match against the filenames in the directory.
///
/// The pattern should contain match groups (expressed in parentheses).
/// Example: "S(\d+)E(\d+).*\.(...)"
///
/// Example: "S(\d+)E(\d+)"
#[arg(short = 's', long)]
pattern: String,
/// Replacement pattern for the matched filenames.
///
/// You can use `\1`, `\2`, etc. to reference the match groups in the pattern.
/// Example: "Season \1 Episode \2.\3"
///
/// There are also the following tags available:
///
/// * {full_name} - file name with extension
///
/// * {name} - filename without extension
///
/// * {ext} - extension
///
/// Example: "Season \1 Episode \2.{ext}"
#[arg(short = 'r', long)]
replacement: String,
@ -42,16 +52,34 @@ fn get_file_list(dir_path: &str, wildcard: &str) -> Vec<String> {
.collect()
}
fn replace_extra_tags(original_file_name: &str, new_file_name: &str) -> String {
let path = Path::new(original_file_name);
let name = path.file_stem().unwrap().to_str().unwrap();
let extension = path.extension().unwrap().to_str().unwrap();
let re = Regex::new(r"(\{[^\{\}]+\})").unwrap();
re.find_iter(new_file_name)
.map(|m| {
let tag = m.as_str();
match tag {
"{ext}" => new_file_name.replace(tag, extension),
"{full_name}" => new_file_name.replace(tag, original_file_name),
"{name}" => new_file_name.replace(tag, name),
_ => panic!("Invalid tag: {}", tag),
}
})
.fold(String::new(), |result, s| result + &s)
}
fn main() {
let args = Args::parse();
let dir_path = &args.path;
let pattern = &args.pattern;
let replacement = &args.replacement;
let wildcard = &args.wildcard;
let files = get_file_list(dir_path, wildcard);
let re = Regex::new(pattern).unwrap();
let files = get_file_list(dir_path, wildcard);
for file_name in files {
for captures in re.captures_iter(&file_name) {
@ -63,6 +91,7 @@ fn main() {
replaced_text = replaced_text.replace(&replace_key, &capture_text);
}
}
replaced_text = replace_extra_tags(&file_name, &replaced_text);
println!("mv \"{}\" \"{}\"", file_name, replaced_text);
}
}