Video Coming Soon...
46: find
The final project in this module is find. Find is a very useful tool that searches through a directory of files--and its children--that match specific patterns. It does a lot more than that though. With find you can do the following (to name a few):
- Find all the files matching a certain regex.
- Print them out or...
- run any command you want on them.
- Or, only process directories that match the regex, or only files.
It does quite a lot, so that's why it's the last project. You could go insane making everything in find work, and I highly recommend you spend some time making the most awesome find possible.
The Challenge
I think find is a little tricky because Go flag package can't really do what find needs. You can get close enough, but at a certain point you'll need to not use flag go out on your own. Other than that find uses most of what you've learned so far, and should be a good final project.
Here's the documentation for find:
Requirements
Nothing new here, you've used all of this:
See the list of requirements
- fmt -- https://pkg.go.dev/fmt
- flag -- https://pkg.go.dev/flag
- path/filepath -- https://pkg.go.dev/path/filepath
- regexp -- https://pkg.go.dev/regexp
- log -- https://pkg.go.dev/log
- io/fs -- https://pkg.go.dev/io/fs
Spoilers
My version of find is very simple. I only find files of type d and f, and I only match on regex recursively. Can you do better?
See my first version code
View Source file go-coreutils/find/main.go Onlypackage main
import (
"fmt"
"flag"
"path/filepath"
"regexp"
"log"
"io/fs"
)
type Opts struct {
Name string
Type string
}
func ParseOpts() Opts {
var opts Opts
flag.StringVar(&opts.Name, "name", "", "regex of file")
flag.StringVar(&opts.Type, "type", "f", "type to find")
flag.Parse()
if flag.NArg() == 0 {
log.Fatal("USAGE: find -name <regex> [-type d/f] <dir> [dir dir]")
}
return opts
}
func main() {
opts := ParseOpts()
re, err := regexp.Compile(opts.Name)
if err != nil { log.Fatal(err) }
for _, start := range flag.Args() {
filepath.WalkDir(start, func (path string, d fs.DirEntry, err error) error {
if err != nil { log.Fatal(err) }
if re.MatchString(path) {
if opts.Type == "" {
fmt.Println(path)
} else if d.IsDir() && opts.Type == "d" {
fmt.Println(path)
} else if !d.IsDir() && opts.Type == "f" {
fmt.Println(path)
}
}
return nil
})
}
}
Testing It
If you want to push your learning further then you can try to implement an automated test for this. I actually need to learn how to test utilities like this with Go, so for now just consider this an extra challenge for later until I learn how to teach it.
Register for The Pro-Webdev Mega Bundle
Register today for the course and get the all currently available videos and lessons, plus all future modules for no extra charge.