012 Project 12: Build a find Clone
012 Build a find Clone
Search recursively by name pattern, type, and min size.
walk tree -> filter (name/type/size) -> print matching paths
Full main.go
package main
import (
"flag"
"fmt"
"io/fs"
"os"
"path/filepath"
"strings"
)
func main() {
name := flag.String("name", "", "substring to match in filename")
typeFlag := flag.String("type", "", "f=file d=dir")
minSize := flag.Int64("min-size", 0, "minimum file size in bytes")
flag.Parse()
root := "."
if flag.NArg() > 0 {
root = flag.Arg(0)
}
err := filepath.WalkDir(root, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return nil
}
base := filepath.Base(path)
if *name != "" && !strings.Contains(strings.ToLower(base), strings.ToLower(*name)) {
return nil
}
if *typeFlag == "f" && d.IsDir() {
return nil
}
if *typeFlag == "d" && !d.IsDir() {
return nil
}
if *minSize > 0 && !d.IsDir() {
info, err := d.Info()
if err != nil || info.Size() < *minSize {
return nil
}
}
fmt.Println(path)
return nil
})
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}Run
go run . /etc -name conf -type f
go run . . -name log -min-size 1048576Step-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.