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}