SideCarJpegCleaner/internal/app/app.go

148 lines
4.4 KiB
Go

/*
* Copyright (C) 2019 Philipp Haefelfinger (http://www.haefelfinger.ch/). All Rights Reserved.
* This application is licensed under GPLv2. See the LICENSE file in the root directory of the project.
*/
package app
import (
"errors"
"flag"
"github.com/sirupsen/logrus"
"github.com/vharitonsky/iniflags"
"os"
"path"
"path/filepath"
"strings"
)
var (
imagesRootPath = flag.String("imagesRootPath", "", "This is the images root path that should be cleaned.")
dryRun = flag.Bool("dryRun", true, "If set to true, all actions are run except the real filesystem modifications")
ignoreDirs arrayFlags
)
func InitializeFlags() {
flag.Var(&ignoreDirs, "ignoreDir", "Directories that should be ignored. Flag can be specified multiple times for more than one directory.")
iniflags.Parse()
}
func Run() {
imagesRootFolder := *imagesRootPath
if imagesRootFolder == "" {
logErrorAndExit(errors.New("No images root folder set, exiting."), 1)
}
err, jpgFiles := findAllJpgFiles(imagesRootFolder)
if err != nil {
logrus.Errorf("Could not clean up %s", imagesRootFolder)
logErrorAndExit(err, 2)
}
filesWithMissingSidecar := getJpegsWithoutRawSideCar(jpgFiles)
logrus.Infof("Found %d of %d images to delete in %s", len(filesWithMissingSidecar), len(jpgFiles), imagesRootFolder)
//todo: this check needs to be performed by each directory and if true, skip the directory but not all
if len(jpgFiles) == len(filesWithMissingSidecar) {
logrus.Warnf("Did not find any sidecar files in %s. Are you sure this is the right path to look for jpgs without raw sidecars? Cancelling executing!", imagesRootFolder)
logErrorAndExit(errors.New("Total files of jpegs and missing sidecars are the same, cancelling!"), 3)
}
if !(*dryRun) {
logrus.Infof("Starting to delete %d files...", len(filesWithMissingSidecar))
deleteFiles(filesWithMissingSidecar)
} else {
logrus.Warnln("Skipping delete of images as flag dryRun is set to true!")
}
}
func deleteFiles(filesWithMissingSidecar []string) {
for _, fileToDelete := range filesWithMissingSidecar {
logrus.Infof("Deleting %s", fileToDelete)
err := os.Remove(fileToDelete)
if err != nil {
logrus.Errorf("Could not delete %s because of %v", fileToDelete, err)
}
}
}
func logErrorAndExit(err error, exitCode int) {
logrus.Errorln(err)
os.Exit(exitCode)
}
func getJpegsWithoutRawSideCar(jpgFiles []string) []string {
var filesWithMissingSidecar []string
for _, jpgFile := range jpgFiles {
dir, fileName := filepath.Split(jpgFile)
newFileName := filenameWithoutExtension(fileName) + ".cr2"
newFilePath := filepath.Join(dir, newFileName)
if exists, err := fileExists(newFilePath); exists {
logrus.Debugf("Found existing sidecar, keeping jpeg %s", jpgFile)
} else if err == nil && !exists {
logrus.Infof("Found jpeg with missing raw file, schedule for delete %s", jpgFile)
filesWithMissingSidecar = append(filesWithMissingSidecar, jpgFile)
} else {
logrus.Errorf("There was an error on checking %s: %v", jpgFile, err)
}
}
return filesWithMissingSidecar
}
func findAllJpgFiles(basePath string) (error, []string) {
var files []string
ignoreDirsMap := make(map[string]struct{}, len(ignoreDirs))
for _, ignoredFolder := range ignoreDirs {
ignoreDirsMap[strings.ToLower(ignoredFolder)] = struct{}{}
}
err := filepath.Walk(basePath, func(path string, info os.FileInfo, err error) error {
if strings.HasPrefix(info.Name(), ".") {
logrus.Debugf("Skipping hidden file or directory %s", path)
if info.IsDir() {
return filepath.SkipDir
}
return nil
}
_, dirIgnored := ignoreDirsMap[strings.ToLower(info.Name())]
if dirIgnored && info.IsDir() {
logrus.Tracef("Skipping ignored directory %s", path)
return filepath.SkipDir
}
extension := strings.ToLower(filepath.Ext(path))
if (extension != ".jpg" && extension != ".jpeg") || info.IsDir() {
return nil
}
logrus.Debugf("Found file %s", path)
files = append(files, path)
return nil
})
return err, files
}
func filenameWithoutExtension(fn string) string {
return strings.TrimSuffix(fn, path.Ext(fn))
}
func fileExists(filePath string) (bool, error) {
_, err := os.Stat(filePath)
if err == nil {
logrus.Debugf("file %s exists", filePath)
return true, nil
} else if os.IsNotExist(err) {
logrus.Debugf("file %s does not exist", filePath)
return false, nil
} else {
logrus.Debugf("file %s stat error: %v", filePath, err)
return false, err
}
}