package filepath
import (
"errors"
"os"
"sort"
)
var SkipDir = errors.New("skip this directory")
var lstat = os.Lstat
type WalkFunc func(path string, info os.FileInfo, err error) error
func Walk(root string, walkFn WalkFunc) error {
info, err := lstat(root)
if err != nil {
err = walkFn(root, nil, err)
} else {
err = walk(root, info, walkFn)
}
if err == SkipDir {
return nil
}
return err
}
func walk(path string, info os.FileInfo, walkFn WalkFunc) error {
if !info.IsDir() {
return walkFn(path, info, nil)
}
names, err := readDirNames(path)
if err != nil {
return walkFn(path, info, err)
}
if err := walkFn(path, info, nil); err != nil {
return err
}
for _, name := range names {
filename := Join(path, name)
fileInfo, err := lstat(filename)
if err != nil {
if err := walkFn(filename, fileInfo, err); err != nil && err != SkipDir {
return err
}
} else {
if err := walk(filename, fileInfo, walkFn); err != nil {
if err != SkipDir {
return err
}
if !fileInfo.IsDir() {
return err
}
}
}
}
return nil
}
func readDirNames(dirname string) ([]string, error) {
f, err := os.Open(dirname)
if err != nil {
return nil, err
}
defer f.Close()
names, err := f.Readdirnames(-1)
if err != nil {
return nil, err
}
sort.Strings(names)
return names, nil
}
样例源码:github.com/morganxf/ex…