GOLANG:走路目录树和进程文件 - 错误='没有这样的文件或目录

时间:2013-12-04 18:04:20

标签: go

我正在编写一个例程来遍历目录树,并为我找到的每个文件创建一个数字签名(salted-hash)。在测试它时,我得到了这种奇怪的行为 - 如果我给程序一个根目录“在”目录之上,程序可以遍历树并打印出文件名,但是如果我尝试打开文件来读取它的字节,我在例程找到的文件上得到错误消息“没有这样的文件或目录” - 不知道这里给出了什么。 Walk()例程如何“查看”该文件,但是ioutil.ReadFile()无法找到它?

示例代码:

// start with path higher up the tree, say $HOME
func doHashWalk(dirPath string) {
    err := filepath.Walk(dirPath, walkFn)
    // Check err here
}

func walkFn(path string, fi os.FileInfo, err error) (e error) {

    if !fi.IsDir() {
        // if the first character is a ".", then skip it as it's a hidden file

        if strings.HasPrefix(fi.Name(), ".") {
            return nil
        }

        // read in the file bytes -> get the absolute path
        fullPath, err := filepath.Abs(fi.Name())
        if err != nil {
            log.Printf("Abs Err: %s", err)
        }

        // THIS ALWAYS FAILED WITH ERROR
        bytes, err := ioutil.ReadFile(fullPath) // <-- (fi.Name() also doesn't work)
        if err != nil {
            log.Printf("Err: %s, Bytes: %d", err, len(bytes))     
        }

        // create the salted hash
        ...
    }
    return nil
}

2 个答案:

答案 0 :(得分:4)

尝试在path内记录fullPathwalkFn的值。

filepath.Abs()内使用walkFn并不能提供您想要的结果:它正在解析相对于当前工作目录的文件名,而不是原始的dirPath。

一个选项是在doHashWalk中预先将目标目录解析为绝对路径:

func doHashWalk(dirPath string) {
    fullPath, err := filepath.Abs(dirPath)

    if err != nil {
        log.Println("path error:", err)

        return
    }

    err = filepath.Walk(fullPath, walkFn)

    // check err here
}

通过该更改,walkFn回调将始终收到完全限定的path参数;无需再次致电filepath.Abs()

func walkFn(path string, fi os.FileInfo, err error) (e error) {
    // ...

    bytes, err := ioutil.ReadFile(path)

    // ...
}

如果您的应用程序看到每个文件相对于原始dirPath根的路径很重要,您可以通过闭包将该路径隐藏到walkFn回调中:

func doHashWalk(dirPath string) error {

    fullPath, err := filepath.Abs(dirPath)

    if err != nil {
        return err
    }

    callback := func(path string, fi os.FileInfo, err error) error {
        return hashFile(fullPath, path, fi, err)
    }

    return filepath.Walk(fullPath, callback)
}

func hashFile(root string, path string, fi os.FileInfo, err error) error {
    if fi.IsDir() {
        return nil
    }

    rel, err := filepath.Rel(root, path)

    if err != nil {
        return err
    }

    log.Println("hash rel:", rel, "abs:", path)

    return nil
}

答案 1 :(得分:0)

问题是你没有按照预期的方式使用filepath.Walk。 您已经从path参数获取了该文件的路径。

docs可能并不十分清楚,但他们确实对filepath说了这么做.Walk:

  

遍历以root为根的文件树,为树中的每个文件或目录调用walkFn ,包括root。

所以你可以将walkFn缩短为这样的东西:

func walkFn(path string, fi os.FileInfo, err error) (e error) {
    if !fi.IsDir() {
        bytes, err := ioutil.ReadFile(path) // path is the path to the file.
        if err != nil {
            fmt.Println("Fail")
        }
    }
    return nil
}

步行将负责不通过..走向文件树,您无需检查。考虑到绝对路径部分我不认为你也需要它,但我没有做出任何承诺;)