007 Project 7: Build an ls Clone
007 Build an ls Clone
This project builds a practical ls-style CLI with flags for hidden files, long format, and sorting.
path -> read entries -> filter -> sort -> format -> print
Full main.go
package main
import (
"flag"
"fmt"
"io/fs"
"os"
"path/filepath"
"sort"
"strings"
"time"
)
type item struct {
Name string
Info fs.FileInfo
}
func main() {
showAll := flag.Bool("a", false, "show hidden files")
longFmt := flag.Bool("l", false, "long listing format")
sortBy := flag.String("sort", "name", "name|size|time")
flag.Parse()
path := "."
if flag.NArg() > 0 {
path = flag.Arg(0)
}
entries, err := os.ReadDir(path)
if err != nil {
fmt.Fprintf(os.Stderr, "read dir failed: %v\n", err)
os.Exit(1)
}
var items []item
for _, e := range entries {
name := e.Name()
if !*showAll && strings.HasPrefix(name, ".") {
continue
}
info, err := e.Info()
if err != nil {
continue
}
items = append(items, item{Name: name, Info: info})
}
sort.Slice(items, func(i, j int) bool {
switch *sortBy {
case "size":
return items[i].Info.Size() < items[j].Info.Size()
case "time":
return items[i].Info.ModTime().Before(items[j].Info.ModTime())
default:
return strings.ToLower(items[i].Name) < strings.ToLower(items[j].Name)
}
})
for _, it := range items {
if *longFmt {
mode := it.Info.Mode().String()
sz := it.Info.Size()
mod := it.Info.ModTime().Format(time.DateTime)
name := it.Name
if it.Info.IsDir() {
name += string(filepath.Separator)
}
fmt.Printf("%s %10d %s %s\n", mode, sz, mod, name)
} else {
fmt.Println(it.Name)
}
}
}Run
go run .
go run . -a -l -sort size /var/logStep-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.