Makefile: add pickrand
[cmccabe-bin] / directory_merge.go
1 package main
2
3 import (
4         "bufio"
5         "errors"
6         "fmt"
7         "io/ioutil"
8         "math"
9         "os"
10         "strings"
11 )
12
13 func usage(retval int) {
14         fmt.Printf("directory_merge: moves files from multiple directories " +
15                 "into a single directory\n");
16         fmt.Printf("usage: directory_merge [destination_directory] " +
17                 "[source_dir 1] ... [source_dir N]\n")
18         os.Exit(retval)
19 }
20
21 type RenamePlan struct {
22         src string
23         dstIdx uint64
24 }
25
26 func (plan *RenamePlan) DstToString(numDigits int) string {
27         return fmt.Sprintf("%0" + fmt.Sprintf("%d", numDigits) + "d", plan.dstIdx);
28 }
29
30 func (plan *RenamePlan) String(dstDir string, numDigits int) string {
31         return plan.src + " -> " + dstDir + "/" + plan.DstToString(numDigits);
32 }
33
34 func (plan *RenamePlan) Execute(dstDir string, numDigits int) error {
35         dstFile := dstDir + "/" + plan.DstToString(numDigits)
36         fmt.Printf("Renaming %s to %s.\n", plan.src, dstFile)
37         err := os.Rename(plan.src, dstFile)
38         if err != nil {
39                 return errors.New(fmt.Sprintf("Failed to rename %s to %s: %v\n",
40                         plan.src, dstFile, err.Error()))
41         }
42         return nil
43 }
44
45 func main() {
46         if (len(os.Args) < 3) {
47                 usage(1)
48         }
49         dstDir := os.Args[1]
50         srcDirs := os.Args[2:]
51         renamePlans := make([]*RenamePlan, 0)
52         var dstIdx uint64
53         for srcDirIdx := range srcDirs {
54                 // ioutil.ReadDir alphabetizes what it returns
55                 srcDir := srcDirs[srcDirIdx]
56                 srcs, err := ioutil.ReadDir(srcDir)
57                 if err != nil {
58                         panic(fmt.Sprintf("Error reading directory %s: %s", srcDir, err))
59                 }
60                 for srcIdx := range srcs {
61                         srcPath := srcDir + "/" + srcs[srcIdx].Name()
62                         dstIdx++
63                         renamePlan := &RenamePlan {
64                                 src: srcPath,
65                                 dstIdx: dstIdx,
66                         }
67                         renamePlans = append(renamePlans, renamePlan)
68                 }
69         }
70         numDigits := int(math.Ceil(math.Log10(float64(dstIdx))))
71         for renamePlanIdx := range renamePlans {
72                 fmt.Printf("%s\n", renamePlans[renamePlanIdx].
73                                                                 String(dstDir, numDigits));
74         }
75         reader := bufio.NewReader(os.Stdin)
76         for {
77                 fmt.Printf("Execute? (y/n):\n")
78                 text, _ := reader.ReadString('\n')
79                 text = strings.TrimSpace(text)
80                 if text == "y" {
81                         break
82                 }
83                 if text == "n" {
84                         fmt.Printf("Aborting.\n");
85                         os.Exit(0)
86                 }
87         }
88         for renamePlanIdx := range renamePlans {
89                 err := renamePlans[renamePlanIdx].Execute(dstDir, numDigits);
90                 if err != nil {
91                         panic(err)
92                 }
93         }
94         os.Exit(0)
95 }