Created
March 2, 2021 09:33
-
-
Save tauraamui/061b2a1c676e69ee2bb03c8eca9eabc2 to your computer and use it in GitHub Desktop.
Go code to concurrently recursively walk file tree counting files, spawning new Goroutine per sub directory found.
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
// Entry point call, pass in valid directory path and nil file pointer | |
total, err := getDirSize("/root/dir/to/count/from", nil) | |
// will either get empty string and pointer or filled string with nil pointer | |
// depending on whether it needs to just count the files still remaining in | |
// this given dir or whether it needs to start counting again in a found sub dir | |
func getDirSize(path string, filePtr *os.File) (int64, error) { | |
var total int64 | |
fp, err := resolveFilePointer(path, filePtr) | |
if err != nil { | |
return total, err | |
} | |
files, err := fp.Readdir(100) | |
if len(files) == 0 { | |
return total, err | |
} | |
total += countFileSizes(files, func(f os.FileInfo) int64 { | |
done := make(chan interface{}) | |
var total int64 | |
go func(d chan interface{}, t *int64) { | |
s, err := getDirSize(fmt.Sprintf("%s%c%s", path, os.PathSeparator, f.Name()), nil) | |
if err != nil { | |
logging.Error("Unable to get dirs full size: %v...", err) | |
} | |
*t += s | |
close(done) | |
}(done, &total) | |
<-done | |
return total | |
}) | |
if err != io.EOF { | |
t, err := getDirSize("", fp) | |
if err == nil { | |
total += t | |
} | |
} | |
return total, nil | |
} | |
func countFileSizes(files []os.FileInfo, onDirFile func(os.FileInfo) int64) int64 { | |
var total int64 | |
for _, f := range files { | |
if f.IsDir() { | |
total += onDirFile(f) | |
continue | |
} | |
if f.Mode().IsRegular() { | |
total += f.Size() | |
} | |
} | |
return total | |
} | |
func resolveFilePointer(path string, file *os.File) (*os.File, error) { | |
var fp *os.File | |
fp = file | |
if fp == nil { | |
filePtr, err := os.Open(path) | |
if err != nil { | |
return nil, err | |
} | |
fp = filePtr | |
} | |
return fp, nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment