123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Drawing.Imaging;
- using System.Drawing;
- using System.IO;
- using System.Text;
- using System.Text.RegularExpressions;
- namespace PhotoSorter
- {
- class Program
- {
- static void Main(string[] args)
- {
- Console.WriteLine("This application can sort photos in CURRENT directory by EXIF shotdate Or it's Filename, move the photos to a NEW sub-Directory which created by date like \"2017-10-01\". Hansi 2017-10-21");
- Console.WriteLine("Press any key to DO it...");
- Console.ReadKey();
- string folderIn = AppDomain.CurrentDomain.BaseDirectory;
- string[] extArray = new string[] {".jpg",".jpeg",".dng",".nef"};
-
- doWork(folderIn, extArray);
- Console.WriteLine("Done!");
- Console.ReadKey();
- }
- static void doWork(string folderIn,string[] extArr)
- {
- for (int exti = 0; exti < extArr.Length; exti++)
- {
- Console.WriteLine("---------Working with " + extArr[exti] + " files!--------------");
- var files = Directory.GetFiles(folderIn, "*" + extArr[exti], SearchOption.TopDirectoryOnly);
- int k = 0;
- Console.WriteLine("Total:" + files.Length.ToString());
- foreach (var file in files)
- {
- k++;
- FileInfo fi = new FileInfo(file);
- Console.WriteLine(k.ToString() + "/" + files.Length.ToString() + "\t" + fi.Name);
- string newFileName;
- if ((fi.Attributes & FileAttributes.Hidden) != FileAttributes.Hidden)
- {
- var dateTaken = GetDateTakenFromImage(file);
- if (dateTaken == DateTime.MinValue)
- {
- Console.WriteLine("ignore " + fi.Name + ":Get Exif Fail");
- Console.WriteLine("Trying to get Date From filename...");
- dateTaken = GetDateFromImageFileName(file);
- if (dateTaken == DateTime.MinValue)
- {
- Console.WriteLine("ignore " + fi.Name + ":Get Date By File Name Fail");
- continue;
- }
- }
- //dateTaken = dateTaken.AddHours(hourOffset);
- //dateTaken = dateTaken.AddMonths(monthOffset);
- var newDir = Path.Combine(Path.GetDirectoryName(file), dateTaken.ToString("yyyy-MM-dd"));
- newFileName = Path.Combine(newDir, Path.GetFileName(file));
- if (!Directory.Exists(Path.GetDirectoryName(newFileName)))
- {
- Directory.CreateDirectory(Path.GetDirectoryName(newFileName));
- }
- //newFileName = Path.Combine(Path.GetDirectoryName(file), dateTaken.ToString("yyyy-MM-dd HHmm.ss") + " " + postfix + ".jpg");
- if (file != newFileName)
- {
- int i = 1;
- while (File.Exists(newFileName))
- {
- newFileName = Path.Combine(Path.GetDirectoryName(file), dateTaken.ToString("yyyy-MM-dd HHmm.ss") + " " + i++ + ".jpg");
- }
- Debug.Assert(!File.Exists(newFileName));
- File.Move(file, newFileName);
- }
- }
- }
- }
- }
- /// <summary>
- /// We init this once so that if the function is repeatedly called
- /// It isn't stressing the garbage man
- /// </summary>
- private static Regex r = new Regex(":");
- /// <summary>
- /// Retrieves the datetime WITHOUT loading the whole image
- /// </summary>
- /// <param name="path"></param>
- /// <returns></returns>
- public static DateTime GetDateTakenFromImage(string path)
- {
- try
- {
- using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
- using (Image myImage = Image.FromStream(fs, false, false))
- {
- PropertyItem propItem = myImage.GetPropertyItem(36867);
- string dateTaken = r.Replace(Encoding.UTF8.GetString(propItem.Value), "-", 2);
- return DateTime.Parse(dateTaken);
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.Message);
- return DateTime.MinValue;
- }
- }
- public static DateTime GetDateFromImageFileName(string path)
- {
- //not finished try to get name from filename. yyyyMMdd or yyyy-MM-dd
- string fn = Path.GetFileNameWithoutExtension(path);
- Regex r1 = new Regex(@"20\d{6}");
- Regex r2 = new Regex(@"20\d{2}-\d{2}-\d{2}");
- if (r1.IsMatch(fn))
- {
- string ff = r1.Match(fn).Value;
- return DateTime.Parse(ff.Substring(0,4)+"/" + ff.Substring(4,2) + "/" + ff.Substring(6,2));
- }
- if (r2.IsMatch(fn))
- {
- string ff = r2.Match(fn).Value;
- return DateTime.Parse(ff);
- }
- return DateTime.MinValue;
- }
- }
- }
|