GOLANG:遍历目录树并处理文件 -- err = '没有这样的文件或目录

use*_*113 3 go

我正在编写一个例程来遍历目录树并为我找到的每个文件创建数字签名(加盐哈希)。在测试它时,我得到了这种奇怪的行为 - 如果我给程序一个目录“上方”的根路径,程序可以遍历树并打印出文件名,但是如果我尝试打开文件以读取它的字节,我在例程找到的文件上收到错误消息“没有这样的文件或目录” - 不确定这里给出了什么。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
}
Run Code Online (Sandbox Code Playgroud)

lnm*_*nmx 5

尝试记录内pathvs.的值。 fullPathwalkFn

使用filepath.Abs()inside ofwalkFn不会给出您想要的结果:它正在解析相对于当前工作目录的文件名,而不是原始的 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
}
Run Code Online (Sandbox Code Playgroud)

进行此更改后,walkFn回调将始终收到完全限定的path参数;无需filepath.Abs()再次调用:

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

    bytes, err := ioutil.ReadFile(path)

    // ...
}
Run Code Online (Sandbox Code Playgroud)

如果您的应用程序了解每个文件相对于原始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
}
Run Code Online (Sandbox Code Playgroud)