1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
pub mod args;
pub mod errors;
pub mod file_renamer;
mod term_utils;
use errors::{InputError, RenameError};
use file_renamer::{FileRenamer, IncrementPosition};
use std::collections::HashSet;
use term_utils::{ask_for_confirmation, log};
pub fn run(opts: args::Options) -> Result<(), RenameError> {
if opts.force && opts.interactive {
return Err(RenameError::InputError(InputError::ForceAndInteractive));
}
let verbose = opts.verbose || opts.dry_run;
let patterns = {
let mut p = Vec::with_capacity(1 + opts.patterns.len());
p.push(opts.pattern);
p.extend(opts.patterns);
p
};
let mut paths = HashSet::new();
let mut count = 0;
for path in &opts.files {
if path.is_file() {
let renamed = {
let mut r = FileRenamer::new(path);
r.apply_patterns(opts.global, &patterns)?;
if let Some(prefix_increment) = opts.prefix_increment {
r.increment(IncrementPosition::Prefix, prefix_increment, count)?;
}
if let Some(suffix_increment) = opts.suffix_increment {
r.increment(IncrementPosition::Suffix, suffix_increment, count)?;
}
r.finish()
};
if path == &renamed {
if verbose {
log(opts.dry_run, format!("No patterns match {:?}", path));
}
continue;
}
if let Some(name) = renamed.file_stem() {
let was_hidden = path
.file_stem()
.unwrap_or_else(|| panic!("No file stem for {:?}?", path))
.to_string_lossy()
.starts_with('.');
if !was_hidden && name.to_string_lossy().starts_with('.') {
log(
opts.dry_run,
format!("WARN: {:?} got prefix '.' and might be hidden.", renamed),
);
}
} else {
return Err(RenameError::InputError(InputError::InvalidRename(
path.to_owned(),
renamed,
)));
}
if renamed.is_dir() {
return Err(RenameError::InputError(
InputError::CannotRenameFileToDirectory(path.to_owned(), renamed),
));
}
if renamed.is_file() || paths.contains(&renamed) {
if opts.interactive {
if !ask_for_confirmation(format!("Overwrite {:?}?", renamed))? {
continue;
}
} else if !opts.force {
return Err(RenameError::InputError(InputError::SkippingOverwrite(
path.to_owned(),
renamed,
)));
}
}
if verbose {
log(opts.dry_run, format!("{:?} -> {:?}", path, renamed));
}
if opts.dry_run {
paths.insert(renamed);
} else {
std::fs::rename(path, renamed)?;
}
count += 1;
} else if opts.ignore_invalid_files {
if verbose {
log(opts.dry_run, format!("Ignoring {:?}", path));
}
} else {
let current = std::env::current_dir()?.join(path);
return Err(RenameError::InputError(InputError::InvalidFile(current)));
}
}
Ok(())
}