func FindMatches(rootDir, pattern string, listDirectories bool) ([]string, error) {
	var matches []string
	matchAny := pattern == "*"
	err := filepath.Walk(rootDir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		rel, _ := filepath.Rel(rootDir, path)
		for _, exclude := range defaultExcludePatterns {
			if ignore, _ := filepath.Match(exclude, rel); ignore {
				if info.IsDir() {
					return filepath.SkipDir
				}
				return nil
			}
		}
		if info.IsDir() {
			if !listDirectories {  
				return nil
			}
		} else if listDirectories {  
			return nil
		}
		matched := matchAny
		if !matchAny {
			name := path
			if !listDirectories {
				name = filepath.Base(name)
			}
			matched, err = filepath.Match(pattern, name)
			if err != nil {
				return err
			}
		}
		if matched {
			matches = append(matches, path)
		}
		return nil
	})
	if len(matches) > 1 {
		sort.Slice(matches, func(i, j int) bool {
			ni := strings.Count(matches[i], string(os.PathSeparator))
			nj := strings.Count(matches[j], string(os.PathSeparator))
			return ni < nj
		})
	}
	return matches, err
}
FindMatches find all matches of a "pattern" reclusively.
Ordered by parent dir.
package utils
import (
	"encoding/json"
	"fmt"
	"io"
	"mime"
	"os"
	"path"
	"path/filepath"
	"sort"
	"strings"
	"sync/atomic"
	"time"
	"github.com/fsnotify/fsnotify"
	"gopkg.in/yaml.v3"
)
func init() {
	mime.AddExtensionType(".go", "text/plain; charset=utf-8")
	mime.AddExtensionType(".mod", "text/plain; charset=utf-8")
	mime.AddExtensionType(".sum", "text/plain; charset=utf-8")
	mime.AddExtensionType(".json", "application/json; charset=utf-8")
	mime.AddExtensionType(".yaml", "application/yaml; charset=utf-8")
	mime.AddExtensionType(".yml", "application/yaml; charset=utf-8")
	mime.AddExtensionType(".toml", "application/toml; charset=utf-8")
	mime.AddExtensionType(".tml", "application/tml; charset=utf-8")
}
func NoOpReadCloser(r io.Reader) io.ReadCloser {
	return noOpCloser{r}
}
type noOpCloser struct {
	io.Reader
}
func (r noOpCloser) Close() error { return nil }
type multiCloser struct {
	io.Reader
	closers []io.ReadCloser
}
func (r multiCloser) Close() (err error) {
	for _, c := range r.closers {
		if cErr := c.Close(); cErr != nil {
			if err == nil {
				err = cErr
			} else {
				err = fmt.Errorf("%v\n%v", err, cErr)
			}
		}
	}
	return
}
func Exists(path string) bool {
	if _, err := os.Stat(path); err != nil {
		return os.IsExist(err)  
	}
	return true
}
func IsDir(path string) bool {
	if f, err := os.Stat(path); err == nil {
		return f.IsDir()
	}
	return false
}
func Ext(s string) string {
	if idx := strings.LastIndexByte(s, '.'); idx > 0 && len(s)-1 > idx {
		ext := s[idx:]  
		if mime.TypeByExtension(ext) != "" {
			return ext
		}
	}
	return ""
}
func Dest(dest string) string {
	if dest == "" {
		dest, _ = os.Getwd()
	} else if s := "%GOPATH%"; strings.Contains(dest, s) {
		gopath := os.Getenv("GOPATH")
		if gopath != "" {
			gopath = filepath.Join(gopath, "src")
			dest = strings.Replace(dest, s, gopath, 1)
		}
	}
	d, err := filepath.Abs(dest)
	if err == nil {
		dest = d
	}
	return filepath.ToSlash(filepath.Clean(dest))
}
var defaultExcludePatterns = []string{
	"*\\node_modules",
	"*\\.git",
}