github.com/scottcagno/storage@v1.8.0/pkg/filesystem/grep.go (about) 1 package filesystem 2 3 import ( 4 "bufio" 5 "fmt" 6 "io" 7 "os" 8 "path/filepath" 9 "regexp" 10 ) 11 12 func GrepWriter(w io.Writer, pattern string, path string) { 13 grep(w, pattern, path) 14 } 15 16 func Grep(pattern string, path string) { 17 grep(os.Stdout, pattern, path) 18 } 19 20 func grep(w io.Writer, pattern string, path string) { 21 // "error check" 22 if w == nil { 23 w = os.Stdout 24 } 25 // compile regex pattern 26 reg, err := regexp.Compile(pattern) 27 if err != nil { 28 return 29 } 30 // "clean" path 31 dir, file := filepath.Split(filepath.ToSlash(path)) 32 // start walking 33 err = filepath.Walk(dir, 34 func(lpath string, info os.FileInfo, err error) error { 35 // clean local path 36 lpath = filepath.ToSlash(lpath) 37 // handle path error 38 if err != nil { 39 fmt.Fprintf(os.Stderr, "prevent panic by handling failure accessing a path %q: %v\n", lpath, err) 40 return err 41 } 42 // check for local file path match 43 fileMatches, _ := filepath.Match(file, lpath) 44 if !info.IsDir() && fileMatches { 45 // do search 46 err = search(w, lpath, reg) 47 if err != nil { 48 return err 49 } 50 } 51 return nil 52 }) 53 // check for errors 54 if err != nil { 55 fmt.Fprintf(os.Stderr, "walk: %T, %+v, %s", err, err, err) 56 } 57 } 58 59 func search(w io.Writer, path string, reg *regexp.Regexp) error { 60 // open file 61 fd, err := os.Open(path) 62 if err != nil { 63 return err 64 } 65 // get scanner and start scanning 66 sc, ln := bufio.NewScanner(fd), 1 67 for sc.Scan() { 68 // check for match in file 69 foundMatch := reg.Match(sc.Bytes()) 70 if foundMatch { 71 fmt.Fprintf(w, "\r%s:%d:%s\n", fd.Name(), ln, sc.Bytes()) 72 //break 73 } 74 ln++ 75 } 76 // close file 77 err = fd.Close() 78 if err != nil { 79 return err 80 } 81 // check scan errors 82 if err := sc.Err(); err != nil { 83 fmt.Fprintf(os.Stderr, "scanner: %T %s\n", err, err) 84 return err 85 } 86 return nil 87 }