diff --git a/src/datetime_tag_parser.rs b/src/datetime_tag_parser.rs new file mode 100644 index 0000000..be1da87 --- /dev/null +++ b/src/datetime_tag_parser.rs @@ -0,0 +1,51 @@ +use exif::{DateTime, In, Tag, Value}; +use std::fs::File; +use std::path::Path; + +pub fn captures(path: &Path) -> Result>, String> { + let file = match File::open(path) { + Ok(f) => f, + Err(e) => return Err(e.to_string()), + }; + + let mut bufreader = std::io::BufReader::new(&file); + let exifreader = exif::Reader::new(); + return match exifreader.read_from_container(&mut bufreader) { + Ok(exif) => { + //for f in exif.fields() { + // println!( + // " {}/{}: {}", + // f.ifd_num.index(), + // f.tag, + // f.display_value().with_unit(&exif) + // ); + // println!(" {:?}", f.value); + //} + // To parse a DateTime-like field, `DateTime::from_ascii` can be used. + match exif.get_field(Tag::DateTime, In::PRIMARY) { + Some(field) => match field.value { + Value::Ascii(ref vec) if !vec.is_empty() => { + match DateTime::from_ascii(&vec[0]) { + Ok(datetime) => Ok(Some(datetime)), + Err(e) => Err(e.to_string()), + } + } + _ => Ok(None), + }, + None => Ok(None), + }; + + //if let Some(field) = exif.get_field(Tag::DateTime, In::PRIMARY) { + // match field.value { + // Value::Ascii(ref vec) if !vec.is_empty() => { + // if let Ok(datetime) = DateTime::from_ascii(&vec[0]) { + // println!("Year of DateTime is {}.", datetime.year); + // } + // } + // _ => {} + // } + //} + } + Err(e) => return Err(e.to_string()), + }; +} diff --git a/src/main.rs b/src/main.rs index 36c175b..e3e1811 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ use clap::Parser; use walkdir::{DirEntry, WalkDir}; +mod datetime_tag_parser; mod parser; mod stats; diff --git a/src/stats.rs b/src/stats.rs index c8a6d92..6f8c5f7 100644 --- a/src/stats.rs +++ b/src/stats.rs @@ -1,7 +1,8 @@ +use crate::datetime_tag_parser; use crate::parser; //use filetime::{set_file_mtime, FileTime}; //use little_exif::metadata::Metadata; -use exif::{DateTime, In, Reader, Tag, Value}; +use exif::{DateTime, In, Tag, Value}; use serde::Serialize; use std::fs::File; use walkdir::DirEntry; @@ -10,18 +11,24 @@ use walkdir::DirEntry; #[derive(Serialize, PartialEq, Debug)] pub struct Stats { num_files: u32, - num_parsed_files: u32, - num_skipped_files: u32, - skipped_files: Vec, + num_files_with_datetime_tag: u32, + num_files_failed_tag_parsing: u32, + num_files_missing_datetime_tag: u32, + num_files_failed_filename_parsing: u32, + filenames_tag_unparseable: Vec, + filenames_name_unparseable: Vec, } impl Stats { fn new() -> Stats { Stats { num_files: 0, - num_parsed_files: 0, - num_skipped_files: 0, - skipped_files: Vec::new(), + num_files_with_datetime_tag: 0, + num_files_failed_tag_parsing: 0, + num_files_missing_datetime_tag: 0, + num_files_failed_filename_parsing: 0, + filenames_tag_unparseable: Vec::new(), + filenames_name_unparseable: Vec::new(), } } } @@ -38,20 +45,27 @@ impl FromIterator for Stats { println!("{} {}", i.path().display(), i.file_name().to_str().unwrap()); + match datetime_tag_parser::captures(i.path()) { + Some(_) => s.num_files_with_datetime_tag += 1, + None => { + s.num_files_missing_datetime_tag += 1; + } + } + let file = File::open(i.path()).unwrap(); let mut bufreader = std::io::BufReader::new(&file); let exifreader = exif::Reader::new(); match exifreader.read_from_container(&mut bufreader) { Ok(exif) => { - for f in exif.fields() { - println!( - " {}/{}: {}", - f.ifd_num.index(), - f.tag, - f.display_value().with_unit(&exif) - ); - println!(" {:?}", f.value); - } + //for f in exif.fields() { + // println!( + // " {}/{}: {}", + // f.ifd_num.index(), + // f.tag, + // f.display_value().with_unit(&exif) + // ); + // println!(" {:?}", f.value); + //} // To parse a DateTime-like field, `DateTime::from_ascii` can be used. if let Some(field) = exif.get_field(Tag::DateTime, In::PRIMARY) { match field.value {