使用filepath在Go中搜索文件。

huangapple go评论96阅读模式
英文:

Search for file in Go using filepath

问题

我正在尝试使用Go语言在目录中查找文件。我正在使用filepath包中的Walk函数。在findFile函数中,我正在获取文件并将其指针分配给传递的文件。但是这似乎不起作用,调用findFile后file的值仍然为nil。请告诉我是否有什么错误或者这种方法不正确。

func example() {
   var file *os.File
   err = filepath.Walk("uploads", findFile(fileId, file))
   if err != nil {
       http.Error(w, err.Error(), http.StatusBadRequest)
       return
   }
}

func findFile(fileId string, file *os.File) func(path string, info os.FileInfo, err error) error {
    return func(path string, info os.FileInfo, err error) error {
        if err != nil {
             return err
        }

        if !info.IsDir() && isFileMatching(info.Name(), fileId) {
             file, err = os.Open(path)
             if err != nil {
                 return err
             }
        }
        return nil
    }
}
英文:

I am trying to find a file in a directory using Go. I am using Walk function from filepath package. In the findFile function, I am getting the file and assigning it the pointer to the file being passed. But this does not seem to work, the value of file after calling findFile is still nil. Please advice if I am doing something wrong or if this approach is not correct.

func example() { 
   var file *os.File
   err = filepath.Walk("uploads", findFile(fileId, file))
   if err != nil {
	   http.Error(w, err.Error(), http.StatusBadRequest)
	   return
   }
}

func findFile(fileId string, file *os.File) func(path string, info os.FileInfo, err error) error {
    return func(path string, info os.FileInfo, err error) error {
	    if err != nil {
		     return err
	    }

	    if !info.IsDir() && isFileMatching(info.Name(), fileId) {
		     file, err = os.Open(path)
		     if err != nil {
			     return err
		     }
	    }
	    return nil
    }

}

答案1

得分: 0

你正在更改指针变量的值,而不是指针所指向的值。

应该是这样的:

f, err := os.Open(path)
if err != nil {
    return err
}
*file = *f

注意:

*file = *f 实际上是 os.File 的一个副本。

这不是一个好的做法。你可能考虑使用通道(和一个 goroutine)来处理这种工作。

你可能还想检查是否只有一个路径可以通过 isFileMatching,或者这是一个文件描述符泄漏(没有关闭已打开的文件)。

英文:

You are change the value of the pointer variable, not the value the pointer pointed to.

It should be:

f, err := os.Open(path)
if err != nil {
    return err
}
*file = *f

Note:

*file = *f is actually a copy of a os.File.

This is not a good practice. You might want to consider using a channel (and a goroutine) for this kind of work.

And you might also want to check if there is only one path that can pass isFileMatching, or it is a file descriptor leak (not closing opened file).

答案2

得分: 0

关于之前的回答,你可以使用切片来收集文件,它们不会被复制,你可以在最后关闭它们。

func example() {
	var files []*os.File
	err := filepath.Walk("uploads", findFile(fileId, &files))
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
}

func findFile(fileId string, files *[]*os.File) func(path string, info os.FileInfo, err error) error {
	return func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if !info.IsDir() && isFileMatching(info.Name(), fileId) {
			file, err := os.Open(path)
			if err != nil {
				return err
			}
			*files = append(*files, file)
		}
		return nil
	}
}
英文:

Regarding the previous answer you can use slice to collect the files, they will not get copied and you can close them all at the end.

func example() {
	var files []*os.File
	err := filepath.Walk("uploads", findFile(fileId, &files))
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
}

func findFile(fileId string, files *[]*os.File) func(path string, info os.FileInfo, err error) error {
	return func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if !info.IsDir() && isFileMatching(info.Name(), fileId) {
			file, err := os.Open(path)
			if err != nil {
				return err
			}
			*files = append(*files, file)
		}
		return nil
	}

}

答案3

得分: 0

另一个选项是使用filepath.WalkDir

package main

import (
   "errors"
   "io/fs"
   "os"
   "path/filepath"
)

func open(root, name string) (*os.File, error) {
   var f *os.File
   filepath.WalkDir(root, func(s string, d fs.DirEntry, e error) error {
      if e != nil { return e }
      if d.Name() != name { return nil }
      f, e = os.Open(s)
      if e != nil { return e }
      return errors.New("found")
   })
   if f == nil {
      return nil, errors.New("not found")
   }
   return f, nil
}

func main() {
   f, e := open(`C:\go`, "path.go")
   if e != nil {
      panic(e)
   }
   defer f.Close()
   println(f.Name())
}

https://golang.org/pkg/path/filepath#WalkDir

英文:

Another option is filepath.WalkDir:

package main

import (
   "errors"
   "io/fs"
   "os"
   "path/filepath"
)

func open(root, name string) (*os.File, error) {
   var f *os.File
   filepath.WalkDir(root, func(s string, d fs.DirEntry, e error) error {
      if e != nil { return e }
      if d.Name() != name { return nil }
      f, e = os.Open(s)
      if e != nil { return e }
      return errors.New("found")
   })
   if f == nil {
      return nil, errors.New("not found")
   }
   return f, nil
}

func main() {
   f, e := open(`C:\go`, "path.go")
   if e != nil {
      panic(e)
   }
   defer f.Close()
   println(f.Name())
}

https://golang.org/pkg/path/filepath#WalkDir

huangapple
  • 本文由 发表于 2021年5月26日 14:56:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/67699952.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定