011 Project 11: Build a du Clone
011 Build a du Clone
Calculate recursive directory size and print human-readable output.
dir walk -> sum file sizes -> print per path + total
Full main.go
package main
import (
"flag"
"fmt"
"io/fs"
"os"
"path/filepath"
)
func human(n int64) string {
units := []string{"B", "KB", "MB", "GB", "TB"}
v := float64(n)
i := 0
for v >= 1024 && i < len(units)-1 {
v /= 1024
i++
}
return fmt.Sprintf("%.1f%s", v, units[i])
}
func dirSize(root string) (int64, error) {
var total int64
err := filepath.WalkDir(root, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return nil
}
if d.IsDir() {
return nil
}
info, err := d.Info()
if err != nil {
return nil
}
total += info.Size()
return nil
})
return total, err
}
func main() {
humanFmt := flag.Bool("h", true, "human readable")
flag.Parse()
args := flag.Args()
if len(args) == 0 {
args = []string{"."}
}
var grand int64
for _, p := range args {
sz, err := dirSize(p)
if err != nil {
fmt.Fprintf(os.Stderr, "%s: %v\n", p, err)
continue
}
grand += sz
if *humanFmt {
fmt.Printf("%8s %s\n", human(sz), p)
} else {
fmt.Printf("%8d %s\n", sz, p)
}
}
if len(args) > 1 {
if *humanFmt {
fmt.Printf("%8s total\n", human(grand))
} else {
fmt.Printf("%8d total\n", grand)
}
}
}Run
go run . -h /var/log /tmpStep-by-Step Explanation
- Parse command-line flags and validate inputs early.
- Keep the core operation in a small, testable function.
- Process data as a stream when possible to reduce memory use.
- Print stable output and meaningful exit codes.
- Add one extension feature and test edge cases.
Code Anatomy
mainhandles flags, orchestration, and errors.- Worker/helper functions hold business logic.
- Output section should be deterministic for scripting and CI usage.
Learning Goals
- Write composable Unix-style Go tools.
- Improve error messages and operator experience.
- Practice iterative improvement over one clear baseline.