package main import ( "bufio" "errors" "fmt" "io/ioutil" "math" "os" "strings" ) func usage(retval int) { fmt.Printf("directory_merge: moves files from multiple directories " + "into a single directory\n"); fmt.Printf("usage: directory_merge [destination_directory] " + "[source_dir 1] ... [source_dir N]\n") os.Exit(retval) } type RenamePlan struct { src string dstIdx uint64 } func (plan *RenamePlan) DstToString(numDigits int) string { return fmt.Sprintf("%0" + fmt.Sprintf("%d", numDigits) + "d", plan.dstIdx); } func (plan *RenamePlan) String(dstDir string, numDigits int) string { return plan.src + " -> " + dstDir + "/" + plan.DstToString(numDigits); } func (plan *RenamePlan) Execute(dstDir string, numDigits int) error { dstFile := dstDir + "/" + plan.DstToString(numDigits) fmt.Printf("Renaming %s to %s.\n", plan.src, dstFile) err := os.Rename(plan.src, dstFile) if err != nil { return errors.New(fmt.Sprintf("Failed to rename %s to %s: %v\n", plan.src, dstFile, err.Error())) } return nil } func main() { if (len(os.Args) < 3) { usage(1) } dstDir := os.Args[1] srcDirs := os.Args[2:] renamePlans := make([]*RenamePlan, 0) var dstIdx uint64 for srcDirIdx := range srcDirs { // ioutil.ReadDir alphabetizes what it returns srcDir := srcDirs[srcDirIdx] srcs, err := ioutil.ReadDir(srcDir) if err != nil { panic(fmt.Sprintf("Error reading directory %s: %s", srcDir, err)) } for srcIdx := range srcs { srcPath := srcDir + "/" + srcs[srcIdx].Name() dstIdx++ renamePlan := &RenamePlan { src: srcPath, dstIdx: dstIdx, } renamePlans = append(renamePlans, renamePlan) } } numDigits := int(math.Ceil(math.Log10(float64(dstIdx)))) for renamePlanIdx := range renamePlans { fmt.Printf("%s\n", renamePlans[renamePlanIdx]. String(dstDir, numDigits)); } reader := bufio.NewReader(os.Stdin) for { fmt.Printf("Execute? (y/n):\n") text, _ := reader.ReadString('\n') text = strings.TrimSpace(text) if text == "y" { break } if text == "n" { fmt.Printf("Aborting.\n"); os.Exit(0) } } for renamePlanIdx := range renamePlans { err := renamePlans[renamePlanIdx].Execute(dstDir, numDigits); if err != nil { panic(err) } } os.Exit(0) }