6

Go限制深度遍历目录下文件

 2 years ago
source link: https://studygolang.com/articles/35613
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Go限制深度遍历目录下文件

uuid · 8天之前 · 586 次点击 · 预计阅读时间 3 分钟 · 大约8小时之前 开始浏览    

Go有提供os.ReadDir、filepath.WalkDir这些方法,很方便得实现遍历指定文件夹下的文件,但是不能很好的限制遍历文件夹深度,这里提供两种方法实现这个功能。

方法1:通过递归实现

package dir

import (
    "os"
    "path/filepath"
)

// 每个文件都会回调这个方法
type WalkFun func(dir, name string, isDir bool) error

func WalkDepth(name string, maxDepth int, fn WalkFun) error {
    return walkDirs([]string{name}, 1, maxDepth, fn)
}

// 遍历每个dirs下的文件,并且返回所有dirs下是目录的文件
func walkDirs(dirs []string, dep, maxDepth int, fn WalkFun) error {
    var subDirs []string
    for _, d := range dirs {
        ff, err := os.ReadDir(d)
        if err != nil {
            return err
        }
        for _, f := range ff {
            err = fn(d, f.Name(), f.IsDir())
            if err != nil {
                return err
            }
            if f.IsDir() { // 如果是目录
                subDirs = append(subDirs, filepath.Join(d, f.Name()))
            }
        }
    }
    if len(subDirs) > 0 && dep < maxDepth {
        return walkDirs(subDirs, dep+1, maxDepth, fn)
    }
    return nil
}

方法2:直接用for实现

package dir

import (
    "os"
    "path/filepath"
)

// 每个文件都会回调这个方法
type WalkFun func(dir, name string, isDir bool) error

func WalkDepth(name string, maxDepth int, fn WalkFun) error {
    var (
        dep = 0 // 深度
        err error
    )
    dirs := []string{name}
    // 如果 dirs下还有dir或已经超出深度时结束循环
    for len(dirs) > 0 && dep != maxDepth {
        dirs, err = WalkDirs(dirs, fn) // 遍历dirs下的文件,返回dirs下目录的文件
        if err != nil {
            return err
        }
        dep++
    }
    return nil
}

// 遍历每个dirs下的文件,并且返回所有dirs下是目录的文件
func WalkDirs(dirs []string, fn WalkFun) ([]string, error) {
    var subDirs []string
    for _, d := range dirs {
        ff, err := os.ReadDir(d)
        if err != nil {
            return nil, err
        }
        for _, f := range ff {
            err = fn(d, f.Name(), f.IsDir())
            if err != nil {
                return nil, err
            }
            if f.IsDir() { // 如果是目录
                subDirs = append(subDirs, filepath.Join(d, f.Name()))
            }
        }
    }
    return subDirs, nil
}

客户端调用:

func main() {
    root := "root"
    err := dir.WalkDepth(root, 2, func(dir, name string, isDir bool) error {
            fmt.Println(dir, name, isDir)
            return nil
        })
    fmt.Println(err)
}
root dir-1-1 true
root dir-1-2 true
root file-1-3 false
root/dir-1-1 f11 true
root/dir-1-2 file-1-2 false

遍历root目录下的深度为2以上的所有文件和目录

两种方法中,递归会比较简洁,但是递归如果深度太深性能会有一定影响,所以可以根据实际需求评估一下。

我的博客:https://itart.cn/blogs/2022/practice/go-read-dir-limit-depth.html


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK