Last active
November 13, 2017 15:52
-
-
Save psychoss/5624ea93c70c3a916a68 to your computer and use it in GitHub Desktop.
Something about deal with file system with Rust
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::thread; | |
use std::fs::{self, DirEntry}; | |
use std::path::{Path, PathBuf}; | |
use std::sync::{Arc, Mutex}; | |
use std::io; | |
macro_rules! or_return { | |
($expr:expr) => (match $expr { | |
::std::result::Result::Ok(val) => val, | |
::std::result::Result::Err(err) =>{ | |
println!("{:?}",err); | |
return;} | |
}) | |
} | |
macro_rules! or_err { | |
($expr:expr,$err:expr) => (match $expr { | |
::std::result::Result::Ok(val) => val, | |
::std::result::Result::Err(err) =>{ | |
$err(err); | |
} | |
}) | |
} | |
macro_rules! unwrap_or_return { | |
($expr:expr) => (match $expr { | |
::std::option::Option::Some(val) => val, | |
::std::option::Option::None =>return, | |
}); | |
($expr:expr,$f:expr) => (match $expr { | |
::std::option::Option::Some(val) =>{ | |
let f=$f; | |
f(val); | |
}, | |
::std::option::Option::None =>return}) | |
} | |
macro_rules! unwrap_none { | |
($expr:expr) => (match $expr { | |
::std::option::Option::Some(val) => val, | |
::std::option::Option::None =>return | |
}); | |
($expr:expr,$f:expr) => (match $expr { | |
::std::option::Option::Some(val) =>{ | |
let f=$f; | |
f(val); | |
}, | |
::std::option::Option::None =>{}}) | |
} | |
macro_rules! or_skip { | |
($expr:expr) => (match $expr { | |
::std::result::Result::Ok(val) => val, | |
::std::result::Result::Err(err) =>continue, | |
}) | |
} | |
macro_rules! unwrap_or_skip { | |
($expr:expr) => (match $expr { | |
::std::option::Option::Some(val) => val, | |
::std::option::Option::None =>continue | |
}) | |
} | |
fn main() { | |
// rename_files_recursive(Path::new("/media/psycho/6661-3337")) | |
// remove_files_recursive(Path::new("/media/psycho/7C1A-EE68/EPUB")) | |
// let dir_reader = match fs::read_dir("/media/psycho/6661-3337") { | |
// Ok(v) => v, | |
// Err(_) => return, | |
// }; | |
// for entry in dir_reader { | |
// match entry { | |
// Ok(v) => { | |
// // println!("Reading directory => {:?}", v.path()); | |
// remove_empty(&v.path()) | |
// // directories.push(v.path()); | |
// } | |
// Err(_) => {} | |
// } | |
// } | |
// let mut directories = vec![]; | |
// let directories_arc = Arc::new(Mutex::new(directories)); | |
// let mut children = vec![]; | |
// for i in 0..3 { | |
// let directories_arc_clone = directories_arc.clone(); | |
// children.push(thread::spawn(move || { | |
// let mut data = directories_arc_clone.lock().unwrap(); | |
// loop { | |
// let mut p = data.pop(); | |
// match p { | |
// Some(ref v) => remove_empty(v, &mut data), | |
// None => {} | |
// } | |
// } | |
// })); | |
// } | |
// for child in children { | |
// let _ = child.join(); | |
// } | |
println!("{:?}", | |
String::from_utf8(decode_url("%5BMathematical.Foundations.of.Computer.\ | |
Networking%282012.4%29%5D.Srinivasan.Keshav.文字版.epub"))); | |
visit_dirs(Path::new("/home/psycho/书籍"), | |
&|dir| { | |
decode_rename(&dir.path()); | |
}); | |
} | |
fn un_hex(cc: u8) -> u8 { | |
match cc { | |
48...57 => cc - 48, | |
65...90 => cc - 55, | |
97...122 => cc - 87, | |
_ => 0, | |
} | |
} | |
fn decode_url(url: &str) -> Vec<u8> { | |
let bytes = url.as_bytes(); | |
let percent_count = bytes.iter().filter(|v| *v == &b'%').count(); | |
// let hexs = &b"0123456789ABCDEF"[..]; | |
let len = bytes.len(); | |
let mut cursor = 0usize; | |
let dst_len = len - 2 * percent_count; | |
let mut vec: Vec<u8> = vec![0;dst_len]; | |
for index in 0..dst_len { | |
if bytes[cursor] == b'%' { | |
vec[index] = un_hex(bytes[cursor + 1]) << 4 | un_hex(bytes[cursor + 2]); | |
cursor += 3; | |
} else { | |
vec[index] = bytes[cursor]; | |
cursor += 1; | |
} | |
if cursor + 1 > len { | |
break; | |
} | |
} | |
vec | |
} | |
fn decode_rename(p: &PathBuf) { | |
let file_name_os = unwrap_or_return!(p.file_stem()); | |
let file_name = unwrap_or_return!(file_name_os.to_str()); | |
let ext = unwrap_or_return!(p.extension()).to_str().unwrap_or(""); | |
let mut fsn = or_return!(String::from_utf8(decode_url(file_name))); | |
fsn = fsn.replace("\u{c}", "-"); | |
fsn = fsn.replace("\u{10}", "-"); | |
fsn = fsn.replace(".", "-"); | |
fsn.push_str("."); | |
fsn.push_str(ext); | |
println!("{:?}", fsn); | |
let mut parent = unwrap_or_return!(p.parent()); | |
let dst = parent.join(fsn); | |
or_err!(fs::rename(p, dst), |err| { | |
println!("{:?}", err); | |
}); | |
} | |
// Remove the directory if it is not contains anything | |
fn remove_empty(p: &PathBuf) { | |
if p.is_file() { | |
return; | |
} | |
match p.read_dir() { | |
Ok(ref mut v) => { | |
// println!("{:?}",v.count()< 1 ); | |
if v.count() < 1 { | |
println!("Remove directory {:?}", p); | |
match fs::remove_dir(p) { | |
Ok(_) => { | |
println!("Removed Empty Directory {:?}", p); | |
} | |
Err(_) => { | |
println!("Remove Empty Directory {:?} was failed", p); | |
} | |
} | |
} | |
} | |
Err(e) => { | |
println!("{:?}", e); | |
} | |
} | |
} | |
fn visit_dirs(dir: &Path, cb: &Fn(&DirEntry)) -> io::Result<()> { | |
if try!(fs::metadata(dir)).is_dir() { | |
for entry in try!(fs::read_dir(dir)) { | |
let entry = try!(entry); | |
let path = entry.path(); | |
if try!(fs::metadata(&path)).is_dir() { | |
let file_name = path.file_name().unwrap().to_str().unwrap(); | |
if !file_name.starts_with("$") { | |
try!(visit_dirs(&path, cb)); | |
} | |
} else { | |
cb(&entry); | |
} | |
} | |
} | |
Ok(()) | |
} | |
fn rename_files_recursive(dir: &Path) { | |
println!("{:?}", dir); | |
visit_dirs(dir, | |
&|dir_entry: &DirEntry| { | |
let p = dir_entry.path(); | |
unwrap_none!(p.extension(), |v| { | |
if v == "pdf" { | |
let mut dst = dir.clone().join("EPUB"); | |
dst = dst.join(p.file_name().unwrap().to_str().unwrap()); | |
fs::rename(&p, dst); | |
} | |
}); | |
}); | |
} | |
fn remove_files_recursive(dir: &Path) { | |
visit_dirs(dir, | |
&|dir_entry: &DirEntry| { | |
let p = dir_entry.path(); | |
match p.extension() { | |
Some(v) => { | |
if v == "gif" { | |
fs::remove_file(&p); | |
} | |
} | |
None => {} | |
} | |
match p.file_name() { | |
Some(v) => { | |
match v.to_str().unwrap() { | |
"hero.jpg" | "logo.png" | "group.png" | "chufa.jpg" | "bj.jpg" => { | |
fs::remove_file(&p); | |
} | |
_ => {} | |
} | |
println!("{:?}", v); | |
} | |
None => {} | |
} | |
}); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extern crate walkdir; | |
extern crate regex; | |
extern crate chrono; | |
use walkdir::WalkDir; | |
use regex::Regex; | |
use chrono::Local; | |
use std::io::{self, Write}; | |
use std::env; | |
use std::fs; | |
macro_rules! wout { ($($tt:tt)*) => { {writeln!($($tt)*)}.unwrap() } } | |
fn short_date()->String{ | |
let dt= Local::now().format("-%Y-%m-%d.").to_string(); | |
dt | |
} | |
fn short_re()->Regex{ | |
Regex::new(r"\d{4}-\d{2}-\d{2}").unwrap() | |
} | |
fn main() { | |
let args: Vec<_> = env::args().collect(); | |
let mut dir: &str = "/home/psycho/Downloads/ACHIEVE/ACHIEVE/Others"; | |
if args.len() > 1 { | |
dir = &args[1]; | |
} | |
println!("The first argument is {}", dir); | |
let re = short_re(); | |
let refind = Regex::new(r"(-master( \([0-9]\))*)*\.").unwrap(); | |
let dt: &str =&short_date(); | |
//let c: &str = &dt; | |
let ite = WalkDir::new(dir); | |
let mut eout = io::stderr(); | |
for entry in ite { | |
match entry { | |
Err(err) => { | |
wout!(eout, "ERROR: {}", err); | |
} | |
Ok(entry) => { | |
let name = entry.path().to_string_lossy().into_owned(); | |
if entry.file_type().is_file() && !re.is_match(&name) { | |
let r = refind.replace_all(&name, dt); | |
match fs::rename(&name, &r) { | |
Err(err) => { | |
wout!(eout, "ERROR: {}", err); | |
} | |
Ok(_) => { | |
println!("{} be renamed to {}", name, r); | |
} | |
} | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment