-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
82 lines (71 loc) · 2.36 KB
/
main.go
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
package main
import (
"log"
"os"
"path/filepath"
"regexp"
"github.com/jessevdk/go-flags"
"github.com/rwcarlsen/goexif/exif"
)
func main() {
var opts struct {
// Supply the directory with pictures as an argument to the program.
// e.g. go run main.go -d /mnt/f/zfest-2024/Unedited\ Photos/
Directory string `short:"d" long:"dir" description:"The directory path which contains the pictures." required:"true"`
DryRun bool `long:"dry-run" description:"Performs a dry run without actually executing the changes."`
}
_, err := flags.Parse(&opts)
if err != nil {
log.Fatal("Exiting...")
}
// Grab the files within the directory
dirEntries, err := os.ReadDir(opts.Directory)
if err != nil {
log.Fatal(err)
}
if opts.DryRun {
log.Print("This is a dry run. No changes will be performed.")
}
// Iterate through the files in the directory
for idx, de := range dirEntries {
// We want the full path of the image. So we join the directory path with the file name.
fullFileName := filepath.Join(opts.Directory, de.Name())
// Open the file.
file, err := os.Open(fullFileName)
if err != nil {
log.Fatal(err)
}
// Decode EXIF data from the file.
exif, err := exif.Decode(file)
if err != nil {
log.Fatal(err)
}
// Grab the time when the image was taken.
taken, err := exif.DateTime()
if err != nil {
log.Fatal(err)
}
// Format the taken time to a filename friendly string.
dateTime := taken.Format("2006-01-02_15-04-05")
//Our original file name can be any of the following patterns:
// AVK00001.jpg
// AVK00002 (2).jpg
// AVK00002 (2) (1).jpg
// We want only the AVKxxxxx.jpg portion and nothing else.
// So we create a RegEx to split the file name to groups.
re := regexp.MustCompile(`((AVK|DSC)[\d]+)(\s*)(\([\d]\)[\s]*)*.jpg`)
// FindStringSubmatch() gets us the captured groups. In our case, we want the first
// group which has the core name.
// We append this to the created date time and join this to the dir name to get the
// new file path.
newFileName := filepath.Join(opts.Directory, dateTime+"_"+re.FindStringSubmatch(de.Name())[1]+".jpg")
// Finally we call os.Rename to rename the file.
if !opts.DryRun {
err = os.Rename(fullFileName, newFileName)
if err != nil {
log.Fatal(err)
}
}
log.Printf("%5v of %5v: %60v -> %60v", (idx + 1), len(dirEntries), fullFileName, newFileName)
}
}