Skip to content

Instantly share code, notes, and snippets.

@crhntr
Last active August 17, 2017 16:59
Show Gist options
  • Save crhntr/cb1fd730261d7ff6fe6e1d56ad4d0d3d to your computer and use it in GitHub Desktop.
Save crhntr/cb1fd730261d7ff6fe6e1d56ad4d0d3d to your computer and use it in GitHub Desktop.
A line counting utility in golang
package main
import (
"bytes"
"flag"
"fmt"
"io"
"log"
"os"
"path/filepath"
)
func main() {
flag.Parse()
patternStrings := flag.Args()
filenMatchCounts := make([]int, len(patternStrings))
lineCounts := make([]int, len(patternStrings))
defer func() {
totalLineseCount := 0
totalFilesMatched := 0
for i, patternString := range patternStrings {
totalLineseCount += lineCounts[i]
totalFilesMatched += filenMatchCounts[i]
fmt.Printf("%8d\t%8d\t%s\n", filenMatchCounts[i], lineCounts[i], patternString)
}
fmt.Printf("\n%8d\t%8d\n", totalFilesMatched, totalLineseCount)
}()
wd, _ := os.Getwd()
walkErr := filepath.Walk(wd, func(path string, info os.FileInfo, err error) error {
// fmt.Printf("\n%8d\t%10d\t%s\n", totalFilesMatched, totalLineseCount, path)
if !info.IsDir() {
for i, pattern := range patternStrings {
if matches, err := filepath.Match(pattern, info.Name()); matches && err == nil {
filenMatchCounts[i]++
file, openErr := os.Open(path)
defer file.Close()
if openErr != nil {
log.Printf("[ERROR] %s", openErr)
return nil
}
count, countErr := lineCounter(file)
if countErr != nil {
log.Printf("[ERROR] %s", countErr)
return nil
}
lineCounts[i] += count
} else if matches && err != nil {
log.Printf("[ERROR] %s", err)
return nil
}
}
}
return nil
})
if walkErr != nil {
fmt.Println("Error: " + walkErr.Error())
}
}
func lineCounter(r io.Reader) (int, error) {
buf := make([]byte, 32*1024)
count := 0
lineSep := []byte{'\n'}
for {
c, err := r.Read(buf)
count += bytes.Count(buf[:c], lineSep)
switch {
case err == io.EOF:
return count, nil
case err != nil:
return count, err
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment