diff --git a/tools/cpdir.go b/tools/cpdir.go new file mode 100644 index 0000000..8d9a537 --- /dev/null +++ b/tools/cpdir.go @@ -0,0 +1,102 @@ +// Copyright 2013 . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ingore + +// +// Copy dir, support regexp. +// +// Example: +// cpdir src dst +// cpdir src dst "\.go$" +// cpdir src dst "\.tiff?$" +// cpdir src dst "\.tiff?|jpg|jpeg$" +// +// Help: +// cpdir -h +// +package main + +import ( + "fmt" + "io" + "io/ioutil" + "log" + "os" + "path/filepath" + "regexp" +) + +const usage = ` +Usage: cpdir src dst [filter] + cpdir -h + +Example: + cpdir src dst + cpdir src dst "\.go$" + cpdir src dst "\.tiff?$" + cpdir src dst "\.tiff?|jpg|jpeg$" + +Report bugs to . +` + +func main() { + if len(os.Args) < 3 { + fmt.Fprintln(os.Stderr, usage[1:len(usage)-1]) + os.Exit(0) + } + filter := ".*" + if len(os.Args) > 3 { + filter = os.Args[3] + } + total := cpDir(os.Args[2], os.Args[1], filter) + fmt.Printf("total %d\n", total) +} + +func cpDir(dst, src, filter string) (total int) { + entryList, err := ioutil.ReadDir(src) + if err != nil && !os.IsExist(err) { + log.Fatal("cpDir: ", err) + } + for _, entry := range entryList { + if entry.IsDir() { + cpDir(dst+"/"+entry.Name(), src+"/"+entry.Name(), filter) + } else { + mathed, err := regexp.MatchString(filter, entry.Name()) + if err != nil { + log.Fatal("regexp.MatchString: ", err) + } + if mathed { + srcFname := filepath.Clean(src + "/" + entry.Name()) + dstFname := filepath.Clean(dst + "/" + entry.Name()) + fmt.Printf("copy %s\n", srcFname) + + cpFile(dstFname, srcFname) + total++ + } + } + } + return +} + +func cpFile(dst, src string) { + err := os.MkdirAll(filepath.Dir(dst), 0666) + if err != nil && !os.IsExist(err) { + log.Fatal("cpFile: ", err) + } + fsrc, err := os.Open(src) + if err != nil { + log.Fatal("cpFile: ", err) + } + defer fsrc.Close() + + fdst, err := os.Create(dst) + if err != nil { + log.Fatal("cpFile: ", err) + } + defer fdst.Close() + if _, err = io.Copy(fdst, fsrc); err != nil { + log.Fatal("cpFile: ", err) + } +} diff --git a/tools/lookpath.go b/tools/lookpath.go new file mode 100644 index 0000000..b8a505c --- /dev/null +++ b/tools/lookpath.go @@ -0,0 +1,44 @@ +// Copyright 2014 . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ingore + +// Lookpath is a simple which. +package main + +import ( + "fmt" + "os" + "os/exec" + "strings" +) + +func main() { + if len(os.Args) < 2 { + fmt.Printf(`Usage: lookpath COMMAND [...] +Write the full path of COMMAND(s) to standard output. + +Report bugs to . +`) + os.Exit(0) + } + for i := 1; i < len(os.Args); i++ { + path, err := exec.LookPath(os.Args[i]) + if err != nil { + fmt.Printf("lookpath: no %s in (%v)\n", os.Args[i], GetEnv("PATH")) + os.Exit(0) + } + fmt.Println(path) + } +} + +func GetEnv(key string) string { + key = strings.ToUpper(key) + "=" + for _, env := range os.Environ() { + if strings.HasPrefix(strings.ToUpper(env), key) { + return env[len(key):] + } + } + return "" +} diff --git a/tools/lsdir.go b/tools/lsdir.go new file mode 100644 index 0000000..9617b66 --- /dev/null +++ b/tools/lsdir.go @@ -0,0 +1,97 @@ +// Copyright 2013 . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ingore + +// +// List files, support file/header regexp. +// +// Example: +// lsdir dir +// lsdir dir "\.go$" +// lsdir dir "\.go$" "chaishushan" +// lsdir dir "\.tiff?|jpg|jpeg$" +// +// Help: +// lsdir -h +// +package main + +import ( + "fmt" + "io/ioutil" + "log" + "os" + "path/filepath" + "regexp" +) + +const usage = ` +Usage: lsdir dir [nameFilter [dataFilter]] + lsdir -h + +Example: + lsdir dir + lsdir dir "\.go$" + lsdir dir "\.go$" "chaishushan" + lsdir dir "\.tiff?|jpg|jpeg$" + +Report bugs to . +` + +func main() { + if len(os.Args) < 2 || os.Args[1] == "-h" { + fmt.Fprintln(os.Stderr, usage[1:len(usage)-1]) + os.Exit(0) + } + dir, nameFilter, dataFilter := os.Args[1], ".*", "" + if len(os.Args) > 2 { + nameFilter = os.Args[2] + } + if len(os.Args) > 3 { + dataFilter = os.Args[3] + } + + total := 0 + filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { + if err != nil { + log.Fatal("filepath.Walk: ", err) + return err + } + if info.IsDir() { + return nil + } + relpath, err := filepath.Rel(dir, path) + if err != nil { + log.Fatal("filepath.Rel: ", err) + return err + } + mathed, err := regexp.MatchString(nameFilter, relpath) + if err != nil { + log.Fatal("regexp.MatchString: ", err) + } + if mathed { + if dataFilter != "" { + data, err := ioutil.ReadFile(path) + if err != nil { + fmt.Printf("ioutil.ReadFile: %s\n", path) + log.Fatal("ioutil.ReadFile: ", err) + } + mathed, err := regexp.MatchString(dataFilter, string(data)) + if err != nil { + log.Fatal("regexp.MatchString: ", err) + } + if mathed { + fmt.Printf("%s\n", relpath) + total++ + } + } else { + fmt.Printf("%s\n", relpath) + total++ + } + } + return nil + }) + fmt.Printf("total %d\n", total) +} diff --git a/tools/md5.go b/tools/md5.go new file mode 100644 index 0000000..f60c8fb --- /dev/null +++ b/tools/md5.go @@ -0,0 +1,121 @@ +// Copyright 2013 . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ingore + +// +// Cacl dir or file MD5Sum, support regexp. +// +// Example: +// md5 file +// md5 dir "\.go$" +// md5 dir "\.tiff?$" +// md5 dir "\.tiff?|jpg|jpeg$" +// +// Help: +// cpdir -h +// +package main + +import ( + "crypto/md5" + "fmt" + "io/ioutil" + "log" + "os" + "path/filepath" + "regexp" + "sort" +) + +const usage = ` +Usage: md5 [dir|file [filter]] + md5 -h + +Example: + md5 file + md5 dir "\.go$" + md5 dir "\.go$" + md5 dir "\.tiff?$" + md5 dir "\.tiff?|jpg|jpeg$" + +Report bugs to . +` + +func main() { + if len(os.Args) < 2 { + fmt.Fprintln(os.Stderr, usage[1:len(usage)-1]) + os.Exit(0) + } + filter := ".*" + if len(os.Args) > 2 { + filter = os.Args[2] + } + + if name := os.Args[1]; IsDir(name) { + m, err := MD5Dir(name, filter) + if err != nil { + log.Fatalf("%s: %v", name, err) + } + var paths []string + for path := range m { + paths = append(paths, path) + } + sort.Strings(paths) + for _, path := range paths { + fmt.Printf("%x *%s\n", m[path], path) + } + } else { + sum, err := MD5File(name) + if err != nil { + log.Fatalf("%s: %v", name, err) + } + fmt.Printf("%x *%s\n", sum, name) + } +} + +func IsDir(name string) bool { + fi, err := os.Lstat(name) + if err != nil { + log.Fatal(err) + } + return fi.IsDir() +} + +func MD5Dir(root string, filter string) (map[string][md5.Size]byte, error) { + m := make(map[string][md5.Size]byte) + err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if info.IsDir() { + return nil + } + mathed, err := regexp.MatchString(filter, path) + if err != nil { + log.Fatal("regexp.MatchString: ", err) + } + if mathed { + data, err := ioutil.ReadFile(path) + if err != nil { + return err + } + m[path] = md5.Sum(data) + } + return nil + }) + if err != nil { + return nil, err + } + return m, nil +} + +func MD5File(filename string) (sum [md5.Size]byte, err error) { + data, err := ioutil.ReadFile(filename) + if err != nil { + return + } + sum = md5.Sum(data) + return +}