Files
date-grouper/main.go
2025-10-01 13:59:04 +02:00

132 lines
2.9 KiB
Go

package main
import (
"flag"
"fmt"
"io"
"os"
"path/filepath"
"regexp"
"time"
logger "git.site.quack-lab.dev/dave/cylogger"
"git.site.quack-lab.dev/dave/cyutils"
)
type DateParser interface {
Parse(s string) (time.Time, error)
}
type DateParser8 struct {
re *regexp.Regexp
}
func (dp *DateParser8) Parse(s string) (time.Time, error) {
matches := dp.re.FindStringSubmatch(s)
if len(matches) == 0 {
return time.Time{}, fmt.Errorf("no match")
}
return time.Parse("20060102", matches[0])
}
type DateParserISO struct {
re *regexp.Regexp
}
func (dp *DateParserISO) Parse(s string) (time.Time, error) {
matches := dp.re.FindStringSubmatch(s)
if len(matches) == 0 {
return time.Time{}, fmt.Errorf("no match")
}
return time.Parse("2006-01-02", matches[0])
}
func main() {
flag.Parse()
logger.InitFlag()
if flag.NArg() == 0 {
logger.Error("no files provided")
return
}
parsers := []DateParser{
&DateParser8{re: regexp.MustCompile(`\d{8}`)},
&DateParserISO{re: regexp.MustCompile(`\d{4}-\d{2}-\d{2}`)},
}
files := flag.Args()
cyutils.WithWorkers(10, files, func(worker int, _ int, file string) {
workerlog := logger.Default.WithPrefix(fmt.Sprintf("worker=%d", worker))
filelog := workerlog.WithPrefix(fmt.Sprintf("file=%q", file))
filelog.Info("processing file")
date, err := parseDate(file, parsers)
if err != nil {
filelog.Error("error parsing date: %s", err)
return
}
filelog.Info("date: %s", date)
datedir := fmt.Sprintf("%04d-%02d-%02d", date.Year(), date.Month(), date.Day())
dest := filepath.Join(datedir, file)
filelog.Info("dest: %s", dest)
err = os.MkdirAll(datedir, 0755)
if err != nil {
filelog.Error("error creating directory: %s", err)
return
}
// Make sure file doesn't exist
destfile, err := os.Stat(dest)
if err == nil {
filelog.Info("dest file already exists: %s", destfile.Name())
return
} else {
if !os.IsNotExist(err) {
filelog.Error("error checking dest file: %s", err)
return
}
}
filelog.Debug("opening input file")
in, err := os.Open(file)
if err != nil {
filelog.Error("error opening file: %s", err)
return
}
filelog.Debug("opening output file %s", dest)
out, err := os.Create(dest)
if err != nil {
filelog.Error("error creating dest file: %s", err)
return
}
filelog.Info("copying file")
_, err = io.Copy(out, in)
if err != nil {
filelog.Error("error copying file: %s", err)
return
}
in.Close()
out.Close()
filelog.Info("removing original file")
err = os.Remove(file)
if err != nil {
filelog.Error("error removing original file: %s", err)
return
}
filelog.Info("moved to %q", dest)
})
}
func parseDate(file string, parsers []DateParser) (time.Time, error) {
for _, parser := range parsers {
date, err := parser.Parse(file)
if err == nil {
return date, nil
}
}
return time.Time{}, fmt.Errorf("no date found")
}