Makefile: add pickrand
[cmccabe-bin] / pickrand.go
1 package main
2
3 import (
4         "bytes"
5         "crypto/rand"
6     "flag"
7         "fmt"
8         "math/big"
9         "os"
10         "path/filepath"
11         "time"
12 )
13
14 func main() {
15     flag.Usage = func() {
16         fmt.Fprintf(os.Stdout, "pickrand.go: picks a random file.\n")
17         fmt.Fprintf(os.Stdout, "\n")
18         flag.PrintDefaults()
19     }
20     prevDays := flag.Int("n", 0, "The number of days back to look.")
21     flag.Parse()
22     var maxDuration time.Duration
23     if (*prevDays != 0) {
24         maxDuration = time.Duration(int64(*prevDays) * (24 * 60 * 60 * 1e9))
25     }
26     
27         root := flag.Arg(0)
28     if (root == "") {
29         root = "."
30     }
31         files := make([]string, 0, 32)
32         err := filepath.Walk(root, func(p string, f os.FileInfo, err error) error {
33                 if err != nil {
34                         return err
35                 }
36         if maxDuration != 0 {
37             var duration = time.Now().Sub(f.ModTime())
38             if duration > maxDuration {
39                 return nil
40             }
41         }
42                 if !f.IsDir() {
43                         files = append(files, p)
44                 }
45                 return nil
46         })
47         if err != nil {
48                 fmt.Fprintf(os.Stderr, "** Error: %s\n", err.Error())
49                 os.Exit(1)
50         }
51     if len(files) == 0 {
52                 fmt.Fprintf(os.Stderr, "No matching files found.\n")
53                 os.Exit(1)
54     }
55         var b [16]byte
56         _, err = rand.Read(b[:])
57         if err != nil {
58                 fmt.Fprintf(os.Stderr, "Failed to access cryptographic randomness.  " +
59                         "Error: %s\n\n", err.Error())
60                 os.Exit(1)
61         }
62         i, err := rand.Int(bytes.NewReader(b[:]), big.NewInt(int64(len(files))))
63         if err != nil {
64                 fmt.Fprintf(os.Stderr, "Failed to get a random int.  Error: %s\n", err.Error())
65                 os.Exit(1)
66         }
67         j := int(i.Uint64())
68
69         fmt.Printf("%s\n", files[j])
70 }