package main import ( "bufio" "fmt" "io/fs" "log" "os" "path/filepath" "regexp" ) const CHANNEL_BUFFERING = 10 type FileMatchData struct { Path string LineIndexes []int Lines []string } func ProcessSingleFile(re_pattern regexp.Regexp, path string, out chan FileMatchData) error { file, err := os.Open(path) if err != nil { log.Fatal(err) } defer file.Close() res := FileMatchData{Path: path, LineIndexes: make([]int, 0), Lines: make([]string, 0)} scanner := bufio.NewScanner(file) // optionally, resize scanner's capacity for lines over 64K, see next example cur_line_ind := 1 for scanner.Scan() { line_text := scanner.Text() if re_pattern.FindString(line_text) != "" { res.LineIndexes = append(res.LineIndexes, cur_line_ind) res.Lines = append(res.Lines, line_text) } cur_line_ind++ } if err := scanner.Err(); err != nil { log.Fatal(err) } out <- res return nil } func main() { path_pattern := "git/hook" re_path_pattern, err := regexp.Compile(path_pattern) if err != nil { fmt.Printf("Unable to compile path pattern Regexp: %v\n", path_pattern) return } text_pattern := "the commit" re_text_pattern, err := regexp.Compile(text_pattern) if err != nil { fmt.Printf("Unable to compile text pattern Regexp: %v\n", text_pattern) return } processed_channel := make(chan FileMatchData, CHANNEL_BUFFERING) total_files := 0 err = filepath.Walk(".", func(path string, info fs.FileInfo, err error) error { if err != nil { fmt.Printf("prevent panic by handling failure accessing a path %q: %v\n", path, err) return err } if re_path_pattern.FindString(path) == "" { return nil } // if info.IsDir() && info.Name() == subDirToSkip { // fmt.Printf("skipping a dir without errors: %+v \n", info.Name()) // return filepath.SkipDir // } if info.IsDir() { return nil } go ProcessSingleFile(*re_text_pattern, path, processed_channel) total_files++ return nil }) for ; total_files > 0; total_files-- { cur_processed := <-processed_channel if len(cur_processed.Lines) == 0 { continue } fmt.Printf("%s:\n", cur_processed.Path) for i := 0; i < len(cur_processed.Lines); i++ { fmt.Printf("%d:%s\n", cur_processed.LineIndexes[i], cur_processed.Lines[i]) } fmt.Print("\n") } if err != nil { fmt.Printf("error walking the path %q: %v\n", path_pattern, err) return } }