package main import ( "flag" "fmt" "log" "os" "regexp" "sync" "sync/atomic" ) func init() { log.SetFlags(log.Lmicroseconds) } func main() { padSize := flag.Int("n", 5, "Pad size for new file names") recreate := flag.Bool("f", false, "First rename all files to .bak and then rename them to iter (to prevent conflicts of already existing files)") flag.Parse() nameFormat := fmt.Sprintf("%%0%dd", *padSize) originalExtensions := make(map[string]string) var mapMutex sync.RWMutex var wg sync.WaitGroup var mutex sync.Mutex extensionRegex := regexp.MustCompile(`\.[a-zA-Z0-9]+$`) var i int32 if *recreate { log.Printf("Recreating all files first") for _, file := range flag.Args() { wg.Add(1) go func(file string) { defer wg.Done() res := extensionRegex.FindAllString(file, -1) if len(res) == 0 { log.Printf("No extension found for file %s", file) return } extension := res[0] bckpFile := file + ".bak" _, err := os.Stat(bckpFile) if !os.IsNotExist(err) { log.Printf("File %s already exists", bckpFile) return } log.Printf("%s -> %s", file, bckpFile) err = os.Rename(file, bckpFile) if err != nil { log.Printf("Error renaming file %s to %s: %s", file, bckpFile, err) } mapMutex.Lock() originalExtensions[bckpFile] = extension mapMutex.Unlock() }(file) } } wg.Wait() wg = sync.WaitGroup{} for _, file := range flag.Args() { wg.Add(1) go func(file string) { defer wg.Done() if *recreate { file = file + ".bak" } info, err := os.Stat(file) if os.IsNotExist(err) { log.Printf("File %s does not exist", file) return } if info.IsDir() { log.Printf("File %s is a directory", file) return } mutex.Lock() atomic.AddInt32(&i, 1) newFile := fmt.Sprintf(nameFormat, i) mutex.Unlock() res := extensionRegex.FindAllString(file, -1) if len(res) == 0 { log.Printf("No extension found for file %s", file) return } extension := res[0] mapMutex.RLock() prevExtension, ok := originalExtensions[file] mapMutex.RUnlock() if ok { extension = prevExtension } newFile = newFile + extension _, err = os.Stat(newFile) if !os.IsNotExist(err) { log.Printf("File %s already exists", newFile) return } log.Printf("%s -> %s", file, newFile) err = os.Rename(file, newFile) if err != nil { log.Printf("Error renaming file %s to %s: %s", file, newFile, err) return } }(file) } wg.Wait() }