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
extern crate chrono;
extern crate exif;
use std::error;
use std::fs;
use std::io;
use std::io::BufReader;
use std::path::Path;
use chrono::{Datelike, NaiveDateTime};
pub fn file_handle(path: &str) -> Result<fs::File, io::Error> {
let file = fs::File::open(path)?;
Ok(file)
}
pub fn exif_data(entry: &fs::DirEntry) -> Result<exif::Reader, exif::Error> {
let file = file_handle(&entry.path().to_str().unwrap())?;
let reader = exif::Reader::new(&mut BufReader::new(file))?;
Ok(reader)
}
pub fn is_jpeg(file: fs::DirEntry) -> Option<fs::DirEntry> {
if let Some(extension) = file.path().extension() {
if let Some(ext) = extension.to_str() {
let lower_ext = String::from(ext).to_lowercase();
if lower_ext == "jpeg" || lower_ext == "jpg" {
return Some(file)
}
}
}
return None
}
pub fn jpegs(path: &Path) -> Result<Vec<fs::DirEntry>, io::Error> {
let jpegs = fs::read_dir(path)?
.filter_map(|f| f.ok())
.filter_map(|f| is_jpeg(f))
.collect::<Vec<fs::DirEntry>>();
Ok(jpegs)
}
pub fn process_jpeg(
file: &fs::DirEntry,
src: &Path,
dest: &Option<Box<&Path>>,
copy: &bool,
overwrite: &bool) -> Result<(), Box<error::Error>> {
let exif_data = exif_data(file)?;
let dt_field = exif_data.get_field(exif::Tag::DateTime, false);
if let Some(dt_field) = dt_field {
let dstr = format!("{}", dt_field.value.display_as(dt_field.tag));
let dt = NaiveDateTime::parse_from_str(&dstr, "%Y-%m-%d %H:%M:%S")?;
let mut target_dir = src.join(format!("{}/{}", dt.year(), dt.month()));
if let Some(dest) = dest {
target_dir = dest.join(format!("{}/{}", dt.year(), dt.month()));
}
if !target_dir.exists() {
fs::create_dir_all(&target_dir)?;
}
let source_file = src.join(file.file_name());
let target_file = target_dir.join(file.file_name());
if target_file.exists() && !*overwrite {
return Err(
Box::new(io::Error::new(
io::ErrorKind::Other,
"file already exists")));
}
if *copy {
fs::copy(source_file, target_file)?;
} else {
fs::rename(source_file, target_file)?;
}
}
Ok(())
}