如何在Golang中使用seekdir / telldir?

时间:2016-09-19 23:24:45

标签: go

我需要在Golang中使用文件系统,并且需要能够在重新启动后恢复扫描。

在C中,我可以通过telldir()执行此操作,然后在恢复时执行seekdir()

Golang只提供filepath.Walk()函数,但无法从特定路径或点开始遍历文件系统。

这使得大型文件系统效率低下

周围有什么办法吗?

2 个答案:

答案 0 :(得分:2)

filepath.walk的签名是:

func Walk(root string, walkFn WalkFunc) error

文档说明它从root指定的目录开始,并且回调函数(walkFn)的签名是:

type WalkFunc func(path string, info os.FileInfo, err error) error

因此,您可以在任何给定目录中开始扫描,并以文件系统作为根目录运行文件系统。您无法从目录开始,但您可以选择性地修剪您正在行走的树。

还有一个"魔法"返回值filepath.SkipDir,它跳过目录(如果在目录上调用回调时返回)或目录中的其余文件(如果在文件上调用回调时返回)。

这可能足以获得您想要的行为,但从您的问题中说出来有点难以理解。你不能打破filepath.Walk调用,然后再恢复它。但是,如果你主要关注回调需要时间来完成,你可以通过在walkFn回调中产生goroutine来解决这个限制。

答案 1 :(得分:0)

您可以编写自己的状态机:
1-使用filepath.Walk()一直走完并缓冲结果,然后使用状态(快速)的缓冲区。

2-将root string保存为暂停状态,然后从头开始扫描,直到到达保存的路径(慢)。

3-您可以使用频道,例如此工作样本:
(试试The Go Playground):

package main

import (
    "fmt"
    "os"
    "path/filepath"
    "sync"
    "time"
)

var dirs = make(chan string, 10)
var wg sync.WaitGroup

func main() {
    wg.Add(1)
    go GetDirectories(`../`, `*`)
    fmt.Println()

    fmt.Println(<-dirs)
    fmt.Println(<-dirs)

    fmt.Println()
    time.Sleep(1 * time.Second) // pause

    for dir := range dirs {
        fmt.Println(dir)
    }
    wg.Wait()
    fmt.Println(`Done.`)
}

// Returns the names of the subdirectories (including their paths)
// that match the specified search pattern in the specified directory.
func GetDirectories(root, pattern string) {
    defer wg.Done()
    defer close(dirs)
    filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
        if !fi.IsDir() {
            return nil
        }
        matched, err := filepath.Match(pattern, fi.Name())
        if err != nil {
            return err
        }
        if !matched {
            return nil
        }
        dirs <- path //dirs = append(dirs, path)
        return nil
    })
}