Created
September 1, 2012 19:52
-
-
Save rudenoise/3585327 to your computer and use it in GitHub Desktop.
A Go program for counting lines in files under a given directory, makes use of parallelism via GoRoutines
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bufio" | |
"flag" | |
"fmt" | |
"io" | |
"os" | |
"path/filepath" | |
"regexp" | |
"sort" | |
"sync" | |
) | |
var exclude = flag.String("exclude", "^$", "regexp pattern to exclude in file path") | |
var include = flag.String("include", "", "regexp pattern to include file path") | |
type File struct { | |
FilePath string | |
LineCount int | |
} | |
type Files []File | |
func (f Files) Len() int { return len(f) } | |
func (f Files) Swap(i, j int) { f[i], f[j] = f[j], f[i] } | |
func (f Files) Less(i, j int) bool { return f[i].LineCount < f[j].LineCount } | |
type ByLengthReverse struct{ Files } | |
func (f ByLengthReverse) Less(i, j int) bool { | |
return f.Files[i].LineCount > f.Files[j].LineCount | |
} | |
func Paths(path string) []string { | |
paths := make([]string, 0) | |
err := filepath.Walk(path, func(cPath string, f os.FileInfo, err error) error { | |
if err != nil { | |
panic(err) | |
} | |
excludeMatch, err := regexp.MatchString(*exclude, cPath) | |
if err != nil { | |
panic(err) | |
} | |
includeMatch, err := regexp.MatchString(*include, cPath) | |
if err != nil { | |
panic(err) | |
} | |
if f.IsDir() == false && excludeMatch == false && includeMatch { | |
paths = append(paths, cPath) | |
} | |
return err | |
}) | |
if err != nil { | |
panic(err) | |
} | |
return paths | |
} | |
func CountLines(filePath string) int { | |
count := 0 | |
contents, err := os.Open(filePath) | |
defer contents.Close() | |
if err != nil { | |
panic(err) | |
} | |
buf := bufio.NewReader(contents) | |
for { | |
read, err := buf.ReadString('\n') | |
if err == io.EOF { | |
break | |
} | |
if err != nil { | |
panic(err) | |
} | |
if read != "" { | |
count++ | |
} | |
} | |
return count | |
} | |
func OpenParallel(paths []string) Files { | |
var files Files | |
var wg sync.WaitGroup | |
for i := 0; i < len(paths); i++ { | |
wg.Add(1) | |
go func(fp string) { | |
lines := CountLines(fp) | |
files = append(files, File{fp, lines}) | |
wg.Done() | |
}(paths[i]) | |
} | |
wg.Wait() | |
return files | |
} | |
func main() { | |
flag.Parse() | |
dir := filepath.Dir(flag.Arg(0)) | |
pths := Paths(dir) | |
limit := 5000 | |
if len(pths) < limit { | |
files := OpenParallel(pths) | |
sort.Sort(ByLengthReverse{files}) | |
for i := 0; i < len(files); i++ { | |
fmt.Printf("%7d\t%s\n", files[i].LineCount, files[i].FilePath) | |
} | |
} else { | |
fmt.Printf("\nDidn't bother, you tried to meaure %d files, limit set to %d\n\n", len(pths), limit) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment