First commit of the day - Beginning of the story
parent
e826b1f032
commit
0351adc51f
|
@ -0,0 +1,232 @@
|
|||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"arrayref 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byte-tools"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.31.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fake-simd"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rdupe"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.1.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "redox_termios"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"digest 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "term"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termion"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "vec_map"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[metadata]
|
||||
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||
"checksum arrayref 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0fd1479b7c29641adbd35ff3b5c293922d696a92f25c8c975da3e0acbc87258f"
|
||||
"checksum atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2fc4a1aa4c24c0718a250f0681885c1af91419d242f29eb8f2ab28502d80dbd1"
|
||||
"checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789"
|
||||
"checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab"
|
||||
"checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40"
|
||||
"checksum byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "73b5bdfe7ee3ad0b99c9801d58807a9dbc9e09196365b0203853b99889ab3c87"
|
||||
"checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536"
|
||||
"checksum digest 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "00a49051fef47a72c9623101b19bd71924a45cca838826caae3eaa4d00772603"
|
||||
"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
||||
"checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d"
|
||||
"checksum libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)" = "6fd41f331ac7c5b8ac259b8bf82c75c0fb2e469bbf37d2becbba9a6a2221965b"
|
||||
"checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd"
|
||||
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
|
||||
"checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637"
|
||||
"checksum sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9eb6be24e4c23a84d7184280d2722f7f2731fcdd4a9d886efbfe4413e4847ea0"
|
||||
"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
|
||||
"checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561"
|
||||
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
|
||||
"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"
|
||||
"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
|
||||
"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
|
||||
"checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c"
|
||||
"checksum walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "63636bd0eb3d00ccb8b9036381b526efac53caf112b7783b730ab3f8e44da369"
|
||||
"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3"
|
||||
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
|
@ -4,3 +4,7 @@ version = "0.1.0"
|
|||
authors = ["Benoît Mauduit <bmauduit@beneth.fr>"]
|
||||
|
||||
[dependencies]
|
||||
clap = "*"
|
||||
term = "*"
|
||||
sha2 = "0.7.1"
|
||||
walkdir = "*"
|
||||
|
|
228
src/main.rs
228
src/main.rs
|
@ -1,3 +1,227 @@
|
|||
fn main() {
|
||||
println!("Hello, world!");
|
||||
extern crate clap;
|
||||
extern crate term;
|
||||
extern crate sha2;
|
||||
extern crate walkdir;
|
||||
|
||||
use sha2::{Sha256, Digest};
|
||||
|
||||
use std::path::Path;
|
||||
use std::process;
|
||||
use std::fs;
|
||||
use std::io::Read;
|
||||
use walkdir::WalkDir;
|
||||
|
||||
const BUFFER_SIZE: usize = 1024;
|
||||
|
||||
/* Note for myself : CLAP = _C_ommand _L_ine _A_rgument _P_arser */
|
||||
use clap::{Arg,ArgMatches, App};
|
||||
|
||||
struct Args {
|
||||
input: String,
|
||||
output: String,
|
||||
vlevel: u8,
|
||||
dryrun: bool,
|
||||
}
|
||||
|
||||
impl Args {
|
||||
fn new(matches: ArgMatches) -> Args {
|
||||
let i = matches.value_of("source").unwrap();
|
||||
let o = matches.value_of("dest").unwrap();
|
||||
|
||||
let vl = match matches.occurrences_of("verbose") {
|
||||
0 => 0,
|
||||
1 => 1,
|
||||
2 => 2,
|
||||
3 | _ => 3,
|
||||
};
|
||||
let dr = matches.is_present("dry-run");
|
||||
|
||||
Args {
|
||||
input: i.to_string(),
|
||||
output: o.to_string(),
|
||||
vlevel: vl,
|
||||
dryrun: dr,
|
||||
}
|
||||
}
|
||||
|
||||
fn path_exist(&self) -> bool {
|
||||
let mut result = true;
|
||||
if ! Path::new(&self.input).exists() {
|
||||
result = false;
|
||||
println!("Error, input ( {} ) is not a valid directory", self.input);
|
||||
}
|
||||
|
||||
if ! Path::new(&self.output).exists() {
|
||||
result = false;
|
||||
println!("Error, output ({} ) is not a valid directory", self.output);
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
fn check_not_same(&self) -> bool {
|
||||
if self.input == self.output {
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fn check_not_parent(&self) -> bool {
|
||||
let vec = vec![&self.input, &self.output];
|
||||
|
||||
for (i, x) in vec.iter().enumerate() {
|
||||
let mut a = Path::new(x);
|
||||
let tmp = match i {
|
||||
0 => &self.output,
|
||||
1 => &self.input,
|
||||
_ => "None",
|
||||
};
|
||||
loop {
|
||||
let b = a.parent();
|
||||
a = match b {
|
||||
Some(b) => {
|
||||
if b.to_str().unwrap() == tmp {
|
||||
return false;
|
||||
}
|
||||
b
|
||||
},
|
||||
None => break,
|
||||
};
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn main() {
|
||||
let mut t = term::stdout().unwrap();
|
||||
let matches = App::new("rdupe")
|
||||
.version("0.1.0")
|
||||
.author("Beneth <bmauduit@beneth.fr>")
|
||||
.about("Symlink identical files from source to dest based on hash")
|
||||
.arg(Arg::with_name("source")
|
||||
.help("Input1 directory (will keep the real file)")
|
||||
.short("i")
|
||||
.long("input")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
)
|
||||
.arg(Arg::with_name("dest")
|
||||
.help("destination directory (will be symlink to real file)")
|
||||
.short("o")
|
||||
.long("dest")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
)
|
||||
.arg(Arg::with_name("dry-run")
|
||||
.short("d")
|
||||
.long("dry-run")
|
||||
.help("Dry run (Compare hash but do not symlink)")
|
||||
)
|
||||
.arg(Arg::with_name("verbose")
|
||||
.short("v")
|
||||
.long("verbose")
|
||||
.multiple(true)
|
||||
.help("Sets the level of verbosity")
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
t.fg(term::color::GREEN).unwrap();
|
||||
let args = Args::new(matches);
|
||||
|
||||
println!("Value for input: {}", args.input);
|
||||
println!("Value for output: {}", args.output);
|
||||
println!("Verbosity Level: {}", args.vlevel);
|
||||
|
||||
if args.dryrun == true {
|
||||
println!("dry-run enabled");
|
||||
} else {
|
||||
if args.vlevel >= 2 {
|
||||
t.fg(term::color::RED).unwrap();
|
||||
println!("dry-run not enabled");
|
||||
t.reset().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
// Check input & output
|
||||
// 1 - Existence
|
||||
if ! args.path_exist() {
|
||||
println!("Exiting: Path 1 or Path 2 does not exist");
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
// 2 - Not the same path
|
||||
if ! args.check_not_same() {
|
||||
println!("Exiting: input and output are the same");
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
// 3 - Coherence (Path1|2 does not contain path1|2)
|
||||
if ! args.check_not_parent() {
|
||||
println!("Exiting: Path1 or Path2 are parent !");
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
// Output
|
||||
for entry in WalkDir::new(&args.output).into_iter().filter_map(|e| e.ok()) {
|
||||
//println!("[O] {}", entry.path().display());
|
||||
|
||||
// symlink_metadata does not follow symlink :-]
|
||||
let metadata = fs::symlink_metadata(entry.path()).unwrap();
|
||||
let ft = metadata.file_type();
|
||||
|
||||
if ft.is_file() {
|
||||
//println!("[I] Name: {}", entry.path().display());
|
||||
|
||||
if let Ok(mut file) = fs::File::open(&entry.path()) {
|
||||
process::<Sha256, _>(&mut file,
|
||||
&format!("{}", entry.path().display()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// let inputs = fs::read_dir(&args.input).unwrap();
|
||||
// for path in inputs {
|
||||
// let path_str = path.unwrap().path().into_os_string().into_string().unwrap();
|
||||
// println!("[I] Name: {}", path_str);
|
||||
|
||||
// if let Ok(mut file) = fs::File::open(&path_str) {
|
||||
// process::<Sha256, _>(&mut file,
|
||||
// &path_str);
|
||||
// }
|
||||
// }
|
||||
|
||||
t.reset().unwrap();
|
||||
t.fg(term::color::CYAN).unwrap();
|
||||
println!("Cheers !");
|
||||
}
|
||||
|
||||
|
||||
/// From https://github.com/RustCrypto/hashes/blob/master/sha2/examples/sha256sum.rs
|
||||
/// Compute digest value for given `Reader` and print it
|
||||
/// On any error simply return without doing anything
|
||||
fn process<D: Digest + Default, R: Read>(reader: &mut R, name: &str) {
|
||||
let mut sh = D::default();
|
||||
let mut buffer = [0u8; BUFFER_SIZE];
|
||||
loop {
|
||||
let n = match reader.read(&mut buffer) {
|
||||
Ok(n) => n,
|
||||
Err(_) => return,
|
||||
};
|
||||
sh.input(&buffer[..n]);
|
||||
if n == 0 || n < BUFFER_SIZE {
|
||||
break;
|
||||
}
|
||||
}
|
||||
print_result(&sh.result(), name);
|
||||
}
|
||||
|
||||
/// Print digest result as hex string and name pair
|
||||
fn print_result(sum: &[u8], name: &str) {
|
||||
for byte in sum {
|
||||
print!("{:02x}", byte);
|
||||
}
|
||||
println!("\t{}", name);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue