Skip to content

Instantly share code, notes, and snippets.

@yunginnanet
Last active January 10, 2025 14:43
Show Gist options
  • Save yunginnanet/aec59fe19e2ddc70e7e2461c46408c30 to your computer and use it in GitHub Desktop.
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)
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