package main import ( "flag" "fmt" "os" "os/exec" "path/filepath" "strconv" "strings" ) var dryrun bool var execCmd string func main() { flag.BoolVar(&dryrun, "n", false, "Show what would have been done.") force := flag.Bool("force", false, "Actually rename files.") flag.StringVar(&execCmd, "exec", "", "Run command on matching file.") path := flag.String("path", ".", "Handle files in path.") flag.Parse() if flag.NArg() == 0 { fmt.Println("No action specified") return } if !dryrun && !*force { panic("please dry run first or use the force flag to actually rename files") } switch flag.Arg(0) { case "normalize": err := filepath.WalkDir(*path, normalize) if err != nil { panic(err) } case "removesuffix": suffix := flag.Arg(1) err := filepath.Walk(*path, removeSuffix(suffix)) if err != nil { panic(err) } removeSuffix(suffix) case "unpack": err := filepath.Walk(*path, unpack) if err != nil { panic(err) } default: fmt.Println("Invalid action specified") return } } func skipDir(filename string) (bool, error) { if filename == "." || filename == ".." { return true, nil } if filename == "Bin" { return true, filepath.SkipDir } return false, nil } func removeSuffix(suffix string) filepath.WalkFunc { return func(p string, f os.FileInfo, err error) error { filename := f.Name() if skip, err := skipDir(filename); skip { return err } element := newMediaElement(p) fmt.Println(element.Path()) dir := filepath.Dir(p) ext := filepath.Ext(filename) filenameNoExt := strings.TrimSuffix(filename, ext) filenameNoSuff := strings.TrimSuffix(filenameNoExt, suffix) if filenameNoSuff != filenameNoExt { newFilename := filenameNoSuff + ext err := rename(filepath.Join(dir, filename), filepath.Join(dir, newFilename), dryrun) if err != nil { fmt.Printf("Could not rename %s: %v\n", filename, err) } } return nil } } func normalize(p string, f os.DirEntry, err error) error { if f == nil || f.IsDir() { return nil } filename := f.Name() if skip, err := skipDir(filename); skip { return err } element := newMediaElement(p) newPath := element.Path() if newPath == p { return nil } return rename(p, newPath, dryrun) } func rename(oldPath, newPath string, dryrun bool) error { fmt.Printf("\nfrom: %s\nto: %s\n", oldPath, newPath) if dryrun { return nil } return os.Rename(oldPath, newPath) } func unpack(p string, f os.FileInfo, err error) error { filename := f.Name() if skip, err := skipDir(filename); skip { return err } ext := filepath.Ext(filename) ext = strings.ToLower(ext) if ext != ".rar" { return nil } cmd := exec.Command(execCmd, p) filename = strings.TrimSuffix(filename, ext) ext = filepath.Ext(filename) if ext == "" { err := cmd.Run() if err != nil { fmt.Printf("Error executing: %v\n", err) } return nil } if strings.HasPrefix(ext, ".part") { ext = ext[5:] part, err := strconv.Atoi(ext) if err == nil && part == 1 { err := cmd.Run() if err != nil { fmt.Printf("Error executing: %v\n", err) } return nil } } return nil }