Last active
January 10, 2025 14:43
-
-
Save yunginnanet/aec59fe19e2ddc70e7e2461c46408c30 to your computer and use it in GitHub Desktop.
take numbered files, sort them, assure equal length, rename (made for ffmpeg frames)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"errors" | |
"fmt" | |
"os" | |
"slices" | |
"strconv" | |
"strings" | |
) | |
func Rename(oldName, newName string, dryRun bool) error { | |
if dryRun { | |
_, _ = os.Stderr.WriteString(fmt.Sprintf("rename %s -> %s\n", oldName, newName)) | |
if _, err := os.Stat(oldName); err != nil { | |
os.Stderr.WriteString(err.Error() + "\n") | |
} | |
return nil | |
} | |
err := os.Rename(oldName, newName) | |
if err != nil { | |
return err | |
} | |
if _, err = os.Stat(newName); err != nil { | |
return err | |
} | |
return nil | |
} | |
func usage(err ...error) { | |
if len(err) == 1 { | |
_, _ = os.Stderr.WriteString(err[0].Error() + "\n") | |
defer func() { | |
os.Exit(1) | |
}() | |
} | |
if err == nil || len(err) == 0 { | |
defer func() { | |
os.Exit(0) | |
}() | |
} | |
_, _ = os.Stderr.WriteString("\n" + | |
"syntax:\n\t" + os.Args[0] + " [-nh] <prefix> <suffix> [start]\n\n" + | |
"\t-n\tdry run\n" + | |
"\t-h\thelp\n\n" + | |
"example:\n\t" + os.Args[0] + " 'img_' '.png' 1\n\n", | |
) | |
} | |
func RenumberFilesInDir(path string, prefix string, suffix string, start int, dryRun bool) error { | |
var err error | |
var fm []os.DirEntry | |
fm, err = os.ReadDir(path) | |
if err != nil { | |
_, _ = os.Stderr.WriteString(err.Error()) | |
return err | |
} | |
oldNums := make([]int, 0, len(fm)) | |
maxLen := 0 | |
numsToNames := make(map[int]string) | |
for _, f := range fm { | |
key := f.Name() | |
if prefix != "" && !strings.HasPrefix(key, prefix) { | |
continue | |
} | |
if suffix != "" && !strings.HasSuffix(key, suffix) { | |
continue | |
} | |
numString := strings.TrimPrefix(key, prefix) | |
numString = strings.TrimSuffix(numString, suffix) | |
num, err := strconv.Atoi(numString) | |
if err != nil { | |
return err | |
} | |
oldNums = append(oldNums, num) | |
numsToNames[num] = key | |
if len(numString) > maxLen { | |
maxLen = len(numString) | |
} | |
} | |
slices.Sort(oldNums) | |
for i := start; i != len(oldNums)-1; i++ { | |
newFile := fmt.Sprintf("%s%0*d%s", prefix, maxLen, i, suffix) | |
Rename(numsToNames[oldNums[i]], newFile, dryRun) | |
} | |
return nil | |
} | |
func main() { | |
var err error | |
dryRun := false | |
var args = make([]string, 0, len(os.Args)) | |
for i, arg := range os.Args { | |
switch { | |
case i == 0: | |
continue | |
case arg == "-h": | |
usage() | |
return | |
case arg == "--dry-run", arg == "-n": | |
dryRun = true | |
_, _ = os.Stderr.WriteString( | |
"dry run enabled, no file operations will occur\n", | |
) | |
default: | |
args = append(args, arg) | |
} | |
} | |
start := 1 | |
if len(args) > 2 { | |
start, err = strconv.Atoi(args[2]) | |
if err != nil { | |
usage(err) | |
} | |
} | |
if len(args) < 2 { | |
usage(errors.New("bad syntax: not enough arguments")) | |
} | |
if err = RenumberFilesInDir("./", args[0], args[1], start, dryRun); err != nil { | |
_, _ = os.Stderr.WriteString(err.Error()) | |
return | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment