arnaucube
arnaucube/exif-datesPublic Self-hosted repository
exif-dates/main.go
main.goRaw
  1package main
  2
  3import (
  4	"errors"
  5	"flag"
  6	"fmt"
  7	"io"
  8	"log"
  9	"os"
 10	"path"
 11	"time"
 12
 13	"github.com/rwcarlsen/goexif/exif"
 14)
 15
 16const version = "v0.0.2_2024-01-26"
 17const layout = "2006-01-02T15:04:05.000Z"
 18
 19func main() {
 20	fmt.Println("version:", version)
 21
 22	var versionFlag bool
 23	var inputDirFlag, outputDirFlag string
 24	flag.BoolVar(&versionFlag, "version", false, "print current version")
 25	flag.BoolVar(&versionFlag, "v", false, "print current version")
 26	flag.StringVar(&inputDirFlag, "input", "./", "input directory")
 27	flag.StringVar(&inputDirFlag, "i", "./", "input directory")
 28	flag.StringVar(&outputDirFlag, "output", "output", "output directory")
 29	flag.StringVar(&outputDirFlag, "o", "output", "output directory")
 30	flag.Parse()
 31
 32	if versionFlag {
 33		os.Exit(0)
 34	}
 35
 36	if err := os.Mkdir(outputDirFlag, os.ModePerm); err != nil {
 37		log.Fatal("output directory already exists")
 38	}
 39
 40	entries, err := os.ReadDir(inputDirFlag)
 41	if err != nil {
 42		log.Fatal(err)
 43	}
 44
 45	for _, e := range entries {
 46		// skip subdirectories
 47		if e.IsDir() {
 48			continue
 49		}
 50
 51		fileName := inputDirFlag + "/" + e.Name()
 52		fileExtension := path.Ext(fileName)
 53		// get file
 54		fmt.Printf("---FileName: %s,", fileName)
 55		f, err := os.Open(fileName)
 56		if err != nil {
 57			fmt.Println("\ne", err)
 58		}
 59		defer f.Close()
 60
 61		// get camera date
 62		date, err := getExifDate(f)
 63		if err != nil && (err == io.EOF || err.Error() == "exif: failed to find exif intro marker") {
 64			fmt.Println("  not an img file, skipping file")
 65			continue
 66		}
 67		if err != nil {
 68			fmt.Println("err", err)
 69			continue
 70		}
 71		fmt.Println("\n  DATE", date)
 72
 73		newFileName := getValidFileName(outputDirFlag+"/"+date.String(), fileExtension)
 74		newFileName = newFileName + fileExtension
 75
 76		fmt.Println("  storing the new img as", newFileName)
 77
 78		// duplicate the original file into newFileName
 79		f, err = os.Open(fileName)
 80		if err != nil {
 81			fmt.Println("\ne", err)
 82		}
 83		defer f.Close()
 84		fo, err := os.Create(newFileName)
 85		if err != nil {
 86			panic(err)
 87		}
 88		defer fo.Close()
 89		buf := make([]byte, 1024)
 90		for {
 91			n, err := f.Read(buf)
 92			if err != nil && err != io.EOF {
 93				panic(err)
 94			}
 95			if n == 0 {
 96				break
 97			}
 98
 99			if _, err := fo.Write(buf[:n]); err != nil {
100				panic(err)
101			}
102		}
103		// set the img date into the file date (file's access and modification times)
104		os.Chtimes(newFileName, *date, *date)
105
106	}
107
108}
109
110func getExifDate(f *os.File) (*time.Time, error) {
111	x, err := exif.Decode(f)
112	if err != nil {
113		return nil, err
114	}
115
116	d, err := x.DateTime()
117	if err != nil {
118		return nil, err
119	}
120
121	return &d, nil
122}
123
124func getValidFileName(fileName, fileExtension string) string {
125	_, err := os.Open(fileName + fileExtension)
126	if !errors.Is(err, os.ErrNotExist) {
127		return getValidFileName(fileName+"_1", fileExtension)
128	}
129	return fileName
130}