package util import ( "os" "path/filepath" ) var WalkerDefaultMinSize int64 = 4096 type Walker struct { Exclude, Include []string MinSize int64 } func matchAny(s string, ref []string) bool { for _, p := range ref { if ok, err := filepath.Match(p, s); err == nil && ok { return ok } } return false } func matchIncludeExclude(s string, incl, excl []string) bool { if incl != nil && !matchAny(s, incl) { return false } if excl != nil && matchAny(s, excl) { return false } return true } func (w *Walker) matches(path string, info os.FileInfo) bool { if !matchIncludeExclude(path, w.Include, w.Exclude) { return false } if info.Mode().IsRegular() && info.Size() < w.MinSize { return false } return true } func (w *Walker) Walk(root string, walkFn filepath.WalkFunc) error { return filepath.Walk(root, func(path string, info os.FileInfo, err error) error { if info.IsDir() { // Only prune directories if they are // excluded. But don't skip the root // directory, even if it matches an exclude // pattern (think "."). if path != root && matchAny(filepath.Base(path), w.Exclude) { return filepath.SkipDir } return nil } if !w.matches(filepath.Base(path), info) { return nil } if !info.Mode().IsRegular() { return nil } walkFn(path, info, err) return nil }) } func NewDefaultWalker() *Walker { return &Walker{ Include: []string{"*.epub", "*.mobi", "*.pdf"}, MinSize: WalkerDefaultMinSize, } }