package utils
import (
"os"
"path/filepath"
"sort"
"strings"
)
type FindFilesOptions struct {
Extension string Recursive bool SkipPrefixes []string SkipHidden bool MinSize int64 }
func FindFiles(rootPath string, opts FindFilesOptions) ([]string, error) {
var results []string
if opts.Recursive {
if err := filepath.Walk(rootPath, makeWalkFunc(&results, opts, rootPath)); err != nil {
return nil, err
}
} else {
if err := scanFlatDir(rootPath, &results, opts); err != nil {
return nil, err
}
}
sort.Strings(results)
return results, nil
}
func makeWalkFunc(results *[]string, opts FindFilesOptions, rootPath string) filepath.WalkFunc {
return func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
name := info.Name()
if opts.SkipHidden && strings.HasPrefix(name, ".") && path != rootPath {
if info.IsDir() {
return filepath.SkipDir
}
return nil
}
if info.IsDir() && path != rootPath {
for _, prefix := range opts.SkipPrefixes {
if strings.HasPrefix(name, prefix) {
return filepath.SkipDir
}
}
return nil
}
if !info.IsDir() {
if fileMatches(name, info, opts) {
*results = append(*results, path)
}
}
return nil
}
}
func fileMatches(name string, info os.FileInfo, opts FindFilesOptions) bool {
if !strings.EqualFold(filepath.Ext(name), opts.Extension) {
return false
}
if info.Size() < opts.MinSize {
return false
}
return true
}
func scanFlatDir(rootPath string, results *[]string, opts FindFilesOptions) error {
entries, err := os.ReadDir(rootPath)
if err != nil {
return err
}
for _, entry := range entries {
if entry.IsDir() {
continue
}
name := entry.Name()
if opts.SkipHidden && strings.HasPrefix(name, ".") {
continue
}
if !strings.EqualFold(filepath.Ext(name), opts.Extension) {
continue
}
path := filepath.Join(rootPath, name)
if info, err := os.Stat(path); err == nil && info.Size() >= opts.MinSize {
*results = append(*results, path)
}
}
return nil
}