You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
156 lines
3.3 KiB
Go
156 lines
3.3 KiB
Go
1 year ago
|
package nfs
|
||
|
|
||
|
import (
|
||
|
"git.noahlan.cn/noahlan/ntool/narr"
|
||
|
"git.noahlan.cn/noahlan/ntool/nstr"
|
||
|
"io/fs"
|
||
|
"os"
|
||
|
"path/filepath"
|
||
|
)
|
||
|
|
||
|
// SearchNameUp find file/dir name in dirPath or parent dirs,
|
||
|
// return the name of directory path
|
||
|
//
|
||
|
// Usage:
|
||
|
//
|
||
|
// repoDir := nfs.SearchNameUp("/path/to/dir", ".git")
|
||
|
func SearchNameUp(dirPath, name string) string {
|
||
|
dir, _ := SearchNameUpx(dirPath, name)
|
||
|
return dir
|
||
|
}
|
||
|
|
||
|
// SearchNameUpx find file/dir name in dirPath or parent dirs,
|
||
|
// return the name of directory path and dir is changed.
|
||
|
func SearchNameUpx(dirPath, name string) (string, bool) {
|
||
|
var level int
|
||
|
dirPath = ToAbsPath(dirPath)
|
||
|
|
||
|
for {
|
||
|
namePath := filepath.Join(dirPath, name)
|
||
|
if PathExists(namePath) {
|
||
|
return dirPath, level > 0
|
||
|
}
|
||
|
|
||
|
level++
|
||
|
prevLn := len(dirPath)
|
||
|
dirPath = filepath.Dir(dirPath)
|
||
|
if prevLn == len(dirPath) {
|
||
|
return "", false
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// WalkDir walks the file tree rooted at root, calling fn for each file or
|
||
|
// directory in the tree, including root.
|
||
|
func WalkDir(dir string, fn fs.WalkDirFunc) error {
|
||
|
return filepath.WalkDir(dir, fn)
|
||
|
}
|
||
|
|
||
|
// GlobWithFunc handle matched file
|
||
|
//
|
||
|
// - TIP: will be not find in subdir.
|
||
|
func GlobWithFunc(pattern string, fn func(filePath string) error) (err error) {
|
||
|
files, err := filepath.Glob(pattern)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
for _, filePath := range files {
|
||
|
err = fn(filePath)
|
||
|
if err != nil {
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
type (
|
||
|
// FilterFunc type for FindInDir
|
||
|
//
|
||
|
// - return False will skip handle the file.
|
||
|
FilterFunc func(fPath string, ent fs.DirEntry) bool
|
||
|
|
||
|
// HandleFunc type for FindInDir
|
||
|
HandleFunc func(fPath string, ent fs.DirEntry) error
|
||
|
)
|
||
|
|
||
|
// OnlyFindDir on find
|
||
|
func OnlyFindDir(_ string, ent fs.DirEntry) bool {
|
||
|
return ent.IsDir()
|
||
|
}
|
||
|
|
||
|
// OnlyFindFile on find
|
||
|
func OnlyFindFile(_ string, ent fs.DirEntry) bool {
|
||
|
return !ent.IsDir()
|
||
|
}
|
||
|
|
||
|
// ExcludeNames on find
|
||
|
func ExcludeNames(names ...string) FilterFunc {
|
||
|
return func(_ string, ent fs.DirEntry) bool {
|
||
|
return !narr.StringsHas(names, ent.Name())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// IncludeSuffix on find
|
||
|
func IncludeSuffix(ss ...string) FilterFunc {
|
||
|
return func(_ string, ent fs.DirEntry) bool {
|
||
|
return nstr.HasOneSuffix(ent.Name(), ss)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// ExcludeDotFile on find
|
||
|
func ExcludeDotFile(_ string, ent fs.DirEntry) bool {
|
||
|
return ent.Name()[0] != '.'
|
||
|
}
|
||
|
|
||
|
// ExcludeSuffix on find
|
||
|
func ExcludeSuffix(ss ...string) FilterFunc {
|
||
|
return func(_ string, ent fs.DirEntry) bool {
|
||
|
return !nstr.HasOneSuffix(ent.Name(), ss)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// ApplyFilters handle
|
||
|
func ApplyFilters(fPath string, ent fs.DirEntry, filters []FilterFunc) bool {
|
||
|
for _, filter := range filters {
|
||
|
if !filter(fPath, ent) {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
// FindInDir code refer the go pkg: path/filepath.glob()
|
||
|
//
|
||
|
// - TIP: will be not find in subdir.
|
||
|
//
|
||
|
// filters: return false will skip the file.
|
||
|
func FindInDir(dir string, handleFn HandleFunc, filters ...FilterFunc) (e error) {
|
||
|
fi, err := os.Stat(dir)
|
||
|
if err != nil || !fi.IsDir() {
|
||
|
return // ignore I/O error
|
||
|
}
|
||
|
|
||
|
// names, _ := d.Readdirnames(-1)
|
||
|
// sort.Strings(names)
|
||
|
|
||
|
des, err := os.ReadDir(dir)
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
for _, ent := range des {
|
||
|
filePath := dir + "/" + ent.Name()
|
||
|
|
||
|
// apply filters
|
||
|
if len(filters) > 0 && ApplyFilters(filePath, ent, filters) {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
if err := handleFn(filePath, ent); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
return nil
|
||
|
}
|