Rewrite: unix renaming script
This commit is contained in:
parent
4c584522a2
commit
658514b8ee
|
@ -1,21 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
print_help() {
|
|
||||||
cat <<HELP
|
|
||||||
Moves the file to a more unix-friendly name
|
|
||||||
|
|
||||||
USAGE: $(basename "$0") <original-path>
|
|
||||||
|
|
||||||
See rename_for_shell.sh for more details on the renaming mechanics. Does not
|
|
||||||
work if the directory also has a bad name
|
|
||||||
|
|
||||||
EXAMPLES:
|
|
||||||
fd -x rename_and_move.sh
|
|
||||||
HELP
|
|
||||||
}
|
|
||||||
|
|
||||||
if [[ -z "$1" || "$1" == "-h" || "$1" == "--help" ]]; then
|
|
||||||
print_help
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
mv -n "$@" "$(~/.configs_pointer/bin/rename_for_shell.sh "$@")" &>/dev/null
|
|
||||||
fi
|
|
|
@ -1,35 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
print_help() {
|
|
||||||
cat <<HELP
|
|
||||||
Converts a given file name to something more sensible
|
|
||||||
|
|
||||||
USAGE: $(basename "$0") <file-name>
|
|
||||||
|
|
||||||
Removes characters that shouldn't be used in file names. Effectively leaves
|
|
||||||
/[0-9A-z-_.]/ with a few additional rules (like no leading hyphens)
|
|
||||||
HELP
|
|
||||||
}
|
|
||||||
|
|
||||||
if [[ -z "$1" ]]; then
|
|
||||||
print_help
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
echo "$@" | awk '{
|
|
||||||
split($0, a, "")
|
|
||||||
|
|
||||||
for (i in a) {
|
|
||||||
c=a[i]
|
|
||||||
|
|
||||||
if (!length(name) && c == "-")
|
|
||||||
continue;
|
|
||||||
else if (c ~ /[0-9A-Za-z_.\-\/]/)
|
|
||||||
name = name c
|
|
||||||
else if (c == " ")
|
|
||||||
name = name "_"
|
|
||||||
else if (c == ":" || c == ";")
|
|
||||||
name = name "-"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
END { print name }'
|
|
||||||
fi
|
|
|
@ -14,7 +14,12 @@ path = "src/prettify_bash_history.rs"
|
||||||
name = "sway_tree"
|
name = "sway_tree"
|
||||||
path = "src/sway_tree.rs"
|
path = "src/sway_tree.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "rename_for_unix"
|
||||||
|
path = "src/rename_for_unix.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "4", features = ["derive"] }
|
clap = { version = "4", features = ["derive"] }
|
||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
regex = "1"
|
regex = "1"
|
||||||
|
termion = "2"
|
||||||
|
|
145
bin/rewritten_in_rust/src/rename_for_unix.rs
Normal file
145
bin/rewritten_in_rust/src/rename_for_unix.rs
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
use clap::Parser;
|
||||||
|
use std::fs;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
use termion::color as tc;
|
||||||
|
|
||||||
|
#[derive(Parser, Debug)]
|
||||||
|
#[command(name = "rename_for_unix", author, version = "0.1.2")]
|
||||||
|
/// Renames a file to a reasonable (no special characters) name
|
||||||
|
///
|
||||||
|
/// Removes leading hyphens. Final file name character set is in /[0-9A-z._-]/, unless the
|
||||||
|
/// --no-caps flag is used
|
||||||
|
struct Args {
|
||||||
|
/// Do not move the file, just print the changes that will be made
|
||||||
|
#[arg(long = "dry-run")]
|
||||||
|
is_dry_run: bool,
|
||||||
|
/// Do not print the new file's path to stdout after moving
|
||||||
|
#[arg(long = "silent")]
|
||||||
|
is_silent: bool,
|
||||||
|
/// Convert all letters to lowercase
|
||||||
|
#[arg(long = "no-caps")]
|
||||||
|
is_no_caps: bool,
|
||||||
|
/// Rename all files/directories in the specified directory, not including itself
|
||||||
|
#[arg(long = "full-directory")]
|
||||||
|
is_full_directory: bool,
|
||||||
|
/// Path to file that'll be renamed
|
||||||
|
#[arg(value_name = "PATH")]
|
||||||
|
original_name: PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
type Try<T> = Result<T, Box<dyn std::error::Error>>;
|
||||||
|
|
||||||
|
fn main() -> Try<()> {
|
||||||
|
let args = Args::parse();
|
||||||
|
let mut to_rename: Vec<PathBuf>;
|
||||||
|
|
||||||
|
// Validate args
|
||||||
|
if args.is_full_directory && args.original_name.is_dir() {
|
||||||
|
to_rename = args.original_name.read_dir()
|
||||||
|
.expect("Unable to read directory")
|
||||||
|
.map(|x| x.expect("IO error while reading directory").path())
|
||||||
|
.collect();
|
||||||
|
} else if args.is_full_directory {
|
||||||
|
eprintln!("Provided path is not a directory. Incompatible option --full-directory");
|
||||||
|
std::process::exit(1);
|
||||||
|
} else {
|
||||||
|
to_rename = vec![args.original_name];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort by length then subsort alphabetically
|
||||||
|
to_rename.sort_by(|a, b| {
|
||||||
|
let sa = a.to_str().unwrap_or("");
|
||||||
|
let sb = b.to_str().unwrap_or("");
|
||||||
|
|
||||||
|
if sa.len() == sb.len() {
|
||||||
|
sa.cmp(&sb)
|
||||||
|
} else {
|
||||||
|
sa.len().cmp(&sb.len())
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
for original_relative_name in to_rename {
|
||||||
|
let original_name = fs::canonicalize(original_relative_name)?;
|
||||||
|
let res_rename = fix_name(&original_name, !args.is_no_caps);
|
||||||
|
|
||||||
|
let og_base_name = original_name.file_name()
|
||||||
|
.unwrap()
|
||||||
|
.to_str()
|
||||||
|
.unwrap_or("<original-base-name>");
|
||||||
|
|
||||||
|
if let Ok(new_name) = res_rename {
|
||||||
|
let new_base_name = new_name.file_name().unwrap();
|
||||||
|
|
||||||
|
if new_name == original_name {
|
||||||
|
continue;
|
||||||
|
} else if new_name.exists() {
|
||||||
|
eprintln!("New file name {:?} already exists.", new_name);
|
||||||
|
eprintln!("{:?}", original_name);
|
||||||
|
eprintln!("{:?}", new_name);
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if args.is_dry_run {
|
||||||
|
println!("{}\"{}\"{} -> {}{:?}{}",
|
||||||
|
tc::Fg(tc::Red), og_base_name, tc::Fg(tc::Reset),
|
||||||
|
tc::Fg(tc::Green), new_base_name, tc::Fg(tc::Reset));
|
||||||
|
} else if !args.is_silent {
|
||||||
|
println!("{}", new_name.to_str().unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
if !args.is_dry_run {
|
||||||
|
fs::rename(original_name, new_name)?;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
eprintln!("Error while moving \"{}\": {:?}", og_base_name, res_rename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fix_name(original_name: &Path, is_caps: bool) -> Try<PathBuf> {
|
||||||
|
let base_name = original_name.file_name().unwrap();
|
||||||
|
|
||||||
|
let mut new_base_name = String::new();
|
||||||
|
let s = &mut new_base_name; // Just an alias
|
||||||
|
|
||||||
|
for c in base_name.to_str().expect("Valid unicode").chars() {
|
||||||
|
match c {
|
||||||
|
'-' if s.is_empty() => continue,
|
||||||
|
':' if s.is_empty() => s.push('_'),
|
||||||
|
';' if s.is_empty() => s.push('_'),
|
||||||
|
'-' => s.push(c),
|
||||||
|
'_' => s.push(c),
|
||||||
|
'.' => s.push(c),
|
||||||
|
' ' => s.push('_'),
|
||||||
|
']' => s.push('_'),
|
||||||
|
':' => s.push('-'),
|
||||||
|
';' => s.push('-'),
|
||||||
|
'&' => s.push_str("_and_"),
|
||||||
|
_ if c.is_digit(10) => s.push(c),
|
||||||
|
_ if c.is_lowercase() => s.push(c),
|
||||||
|
_ if c.is_uppercase() && is_caps => s.push(c),
|
||||||
|
_ if c.is_uppercase() => s.push(c.to_ascii_lowercase()),
|
||||||
|
_ => continue,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combine consecutive underscores
|
||||||
|
let c1 = s.chars().rev().nth(0).unwrap_or('a');
|
||||||
|
let c2 = s.chars().rev().nth(1).unwrap_or('a');
|
||||||
|
|
||||||
|
if c1 == '_' && c2 == '_' {
|
||||||
|
s.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't make dot file if it wasn't one initially
|
||||||
|
let og_first_char = original_name.to_str().unwrap().chars().next().unwrap_or('_');
|
||||||
|
let new_first_char = new_base_name.chars().next().unwrap_or('_');
|
||||||
|
|
||||||
|
if og_first_char != '.' && new_first_char == '.' {
|
||||||
|
new_base_name.insert(0, '_');
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(original_name.with_file_name(&new_base_name))
|
||||||
|
}
|
Loading…
Reference in a new issue