Compare commits

..

2 Commits

Author SHA1 Message Date
zomo
4de0cee7c6 v1.0.9 improved file move and folder deletion logic 2025-11-14 21:52:14 -06:00
zomo
ca76fea1da v1.0.8 filename length limit 2025-08-26 12:04:24 -05:00
5 changed files with 85 additions and 41 deletions

View File

@@ -2,3 +2,5 @@ LIBRARY_ROOT= # root directory for library
LIBRARY_FILETEMPLATE_PATH= # go text/template string that represents the path in the library LIBRARY_FILETEMPLATE_PATH= # go text/template string that represents the path in the library
LIBRARY_FILETEMPLATE_FILE= # go text/template string that represents the file name in the library path LIBRARY_FILETEMPLATE_FILE= # go text/template string that represents the file name in the library path
LIBRARY_NOTAGS_ROOT= # path to put files without tags LIBRARY_NOTAGS_ROOT= # path to put files without tags
FILENAME_LIMIT= # max length of a filename, default 255

2
go.mod
View File

@@ -9,4 +9,4 @@ require (
github.com/joho/godotenv v1.5.1 github.com/joho/godotenv v1.5.1
) )
require golang.org/x/text v0.26.0 // indirect require golang.org/x/text v0.28.0

4
go.sum
View File

@@ -2,5 +2,5 @@ github.com/dhowden/tag v0.0.0-20240417053706-3d75831295e8 h1:OtSeLS5y0Uy01jaKK4m
github.com/dhowden/tag v0.0.0-20240417053706-3d75831295e8/go.mod h1:apkPC/CR3s48O2D7Y++n1XWEpgPNNCjXYga3PPbJe2E= github.com/dhowden/tag v0.0.0-20240417053706-3d75831295e8/go.mod h1:apkPC/CR3s48O2D7Y++n1XWEpgPNNCjXYga3PPbJe2E=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=

120
main.go
View File

@@ -9,6 +9,7 @@ import (
"log" "log"
"os" "os"
"path" "path"
"strconv"
"strings" "strings"
"text/template" "text/template"
"time" "time"
@@ -92,7 +93,6 @@ func getDir() (string, error) {
} }
func mainPath(directory string) error { func mainPath(directory string) error {
if err := testEnv(); err != nil { if err := testEnv(); err != nil {
return err return err
} }
@@ -108,8 +108,8 @@ func mainPath(directory string) error {
// read tags // read tags
tags, _ := getTagsInDir(directory) tags, _ := getTagsInDir(directory)
// move files
if tags != nil { if tags != nil {
// move tagged folder
if printLogs { if printLogs {
log.Println("found tags, moving based on tags") log.Println("found tags, moving based on tags")
} }
@@ -118,6 +118,7 @@ func mainPath(directory string) error {
return err return err
} }
} else { } else {
// move untagged folder
if printLogs { if printLogs {
log.Println("no tags found, moving to notags folder") log.Println("no tags found, moving to notags folder")
} }
@@ -127,6 +128,17 @@ func mainPath(directory string) error {
} }
} }
// delete folder
time.Sleep(1 * time.Second)
files, err = os.ReadDir(directory)
if err != nil {
return err
}
if len(files) == 0 {
return os.Remove(directory)
}
return nil return nil
} }
@@ -151,9 +163,34 @@ func testEnv() error {
return errors.New("missing LIBRARY_NOTAGS_ROOT") return errors.New("missing LIBRARY_NOTAGS_ROOT")
} }
if !testEnvFilenameLimit() {
return errors.New("unable to parse FILENAME_LIMIT")
}
return nil return nil
} }
func testEnvFilenameLimit() bool {
limit, ok := os.LookupEnv("FILENAME_LIMIT")
if !ok {
return true
}
_, err := strconv.Atoi(limit)
return err == nil
}
func getEnvFilenameLimit() int {
limit, ok := os.LookupEnv("FILENAME_LIMIT")
if !ok {
return 255
}
limit_i, err := strconv.Atoi(limit)
if err != nil {
return 255
}
return limit_i
}
func getTagsInDir(directory string) (tag.Metadata, error) { func getTagsInDir(directory string) (tag.Metadata, error) {
files, err := os.ReadDir(directory) files, err := os.ReadDir(directory)
if err != nil { if err != nil {
@@ -210,7 +247,30 @@ func doMoveNotags(directory string) error {
_, folderName := path.Split(directory) _, folderName := path.Split(directory)
toDirectory := path.Join(newRoot, folderName) toDirectory := path.Join(newRoot, folderName)
return move(directory, toDirectory) files, err := os.ReadDir(directory)
if err != nil {
return err
}
for _, file := range files {
if file.IsDir() {
continue
}
if file.Name()[0] == '.' {
continue
}
filefrom := path.Join(directory, file.Name())
fileto := path.Join(toDirectory, file.Name())
err = moveFile(filefrom, fileto)
if err != nil {
return err
}
}
return nil
} }
func doMoveTags(directory string, albumTags tag.Metadata) error { func doMoveTags(directory string, albumTags tag.Metadata) error {
@@ -241,7 +301,7 @@ func doMoveTags(directory string, albumTags tag.Metadata) error {
continue continue
} }
err = doMoveTagged(fname, tags) err = doMoveTaggedFile(fname, tags)
if err != nil { if err != nil {
return err return err
} }
@@ -260,33 +320,12 @@ func doMoveTags(directory string, albumTags tag.Metadata) error {
fname := path.Join(directory, file.Name()) fname := path.Join(directory, file.Name())
err = doMoveTaggedPathonly(fname, albumTags) err = doMoveTaggedFileExtras(fname, albumTags)
if err != nil { if err != nil {
return err return err
} }
} }
// delete folder
files, err = os.ReadDir(directory)
if err != nil {
return err
}
if len(files) == 0 {
return os.Remove(directory)
}
// some files remain, wait a second to see if they go away
time.Sleep(1 * time.Second)
files, err = os.ReadDir(directory)
if err != nil {
return err
}
if len(files) == 0 {
return os.Remove(directory)
}
return nil return nil
} }
@@ -311,7 +350,7 @@ type LibTemplateFile struct {
DiscCount int DiscCount int
} }
func doMoveTagged(filePath string, fileTags tag.Metadata) error { func doMoveTaggedFile(filePath string, fileTags tag.Metadata) error {
libRoot := os.Getenv("LIBRARY_ROOT") libRoot := os.Getenv("LIBRARY_ROOT")
libTemplatePath := os.Getenv("LIBRARY_FILETEMPLATE_PATH") libTemplatePath := os.Getenv("LIBRARY_FILETEMPLATE_PATH")
libTemplateFile := os.Getenv("LIBRARY_FILETEMPLATE_FILE") libTemplateFile := os.Getenv("LIBRARY_FILETEMPLATE_FILE")
@@ -356,12 +395,18 @@ func doMoveTagged(filePath string, fileTags tag.Metadata) error {
return err return err
} }
libFile := path.Join(libRoot, bufPath.String(), bufFile.String() + fileExt) filenameLimit := getEnvFilenameLimit() - len(fileExt)
filename := bufFile.String()
return move(filePath, libFile) if len(filename) > filenameLimit {
filename = filename[:filenameLimit]
} }
func doMoveTaggedPathonly(filePath string, albumTags tag.Metadata) error { libFile := path.Join(libRoot, bufPath.String(), filename + fileExt)
return moveFile(filePath, libFile)
}
func doMoveTaggedFileExtras(filePath string, albumTags tag.Metadata) error {
libRoot := os.Getenv("LIBRARY_ROOT") libRoot := os.Getenv("LIBRARY_ROOT")
libTemplatePath := os.Getenv("LIBRARY_FILETEMPLATE_PATH") libTemplatePath := os.Getenv("LIBRARY_FILETEMPLATE_PATH")
_, fileName := path.Split(filePath) _, fileName := path.Split(filePath)
@@ -383,7 +428,7 @@ func doMoveTaggedPathonly(filePath string, albumTags tag.Metadata) error {
libFile := path.Join(libRoot, bufPath.String(), fileName) libFile := path.Join(libRoot, bufPath.String(), fileName)
return move(filePath, libFile) return moveFile(filePath, libFile)
} }
func ensureDirectoryPath(filePath string) error { func ensureDirectoryPath(filePath string) error {
@@ -391,7 +436,7 @@ func ensureDirectoryPath(filePath string) error {
return os.MkdirAll(directoryPath, 0777) return os.MkdirAll(directoryPath, 0777)
} }
func move(from, to string) error { func moveFile(from, to string) error {
to = cleanPath(to) to = cleanPath(to)
if _, err := os.Stat(to); err == nil { if _, err := os.Stat(to); err == nil {
return fmt.Errorf("file already exists: %s", to) return fmt.Errorf("file already exists: %s", to)
@@ -404,14 +449,11 @@ func move(from, to string) error {
if printLogs { if printLogs {
log.Printf("moving \"%s\" => \"%s\"\n", from, to) log.Printf("moving \"%s\" => \"%s\"\n", from, to)
} }
// os.Rename gives error "invalid cross-device link"
if err := os.Rename(from, to); err != nil { return moveFileWrite(from, to)
return moveFile(from, to)
}
return nil
} }
func moveFile(source, destination string) (err error) { func moveFileWrite(source, destination string) (err error) {
src, err := os.Open(source) src, err := os.Open(source)
if err != nil { if err != nil {
return err return err

Binary file not shown.