Go语言中与目录操作相关的函数
这个主题也有我个人备忘录的色彩。我写这个的原因之一是为了”记忆”。
这个问题非常简单。
搜索目录,找到与Dockerfile匹配的内容,并获取该目录中的元数据和目录名称。这个非常简单。问题在于我忘记了如何在Go中编写它。所以我决定写一篇博客来整理一下。
当前目录
currentDir := os.Getwd()
合并文件路径
由于不同的平台合并文件路径的方法不同,如果自己拼接的话会非常麻烦。
Join函数的参数是可变长的字符串,可以轻松转换为列表。
path := filepath.Join(currentDir, "tests", "images)
顺便提一下,…被称为省略号。想要将[]string转换为省略号的情况是。
param := []string{ CurrentDir, "tests", "images" }
path := filepath.Join(param...)
如果要进行操作的话,最好这样做。顺便说一下,`filepath.Join(CurrentDir, param…)`不起作用。Join函数的参数只能是Ellipsis。
进行目录搜索。
在进行目录搜索时,主要有三种方法。
获取目录列表
获取特定目录的列表。
dirs, err := ioutil.ReadDir(path)
顺便提一下,返回值是一个 FileInfo 结构体,并且包含了这些值。
// A FileInfo describes a file and is returned by Stat.
type FileInfo interface {
Name() string // base name of the file
Size() int64 // length in bytes for regular files; system-dependent for others
Mode() FileMode // file mode bits
ModTime() time.Time // modification time
IsDir() bool // abbreviation for Mode().IsDir()
Sys() interface{} // underlying data source (can return nil)
}
全球
如果您想要使用模式匹配进行搜索,可以使用 Glob。
target := filepath.Join(path, "*/Dockerfile"
dirs := filepath.Glob(target)
起初,我希望它可以匹配多个目录,但实际上只能匹配单层目录。
使用WalkDir进行递归搜索
最后的模式是WalkDir。它可以递归地进行搜索。尽管名为Dir,但它也可以搜索文件。顺便提一下,虽然还有一个名为Walk的函数,但不需要使用它。从go 1.16开始引入了WalkDir,并且这个方法似乎更有效率。
正如你看到的,当传递一个函数时,它会在找到目录或文件时进行调用。
顺便提一下,filepath.Base() 在文件的完整路径中,只返回最后一个元素(也就是文件名)。
err = filepath.WalkDir(currentDir, func(path string, d fs.DirEntry, err error) error {
if !d.Dir() {
fmt.Printf("Base: %ss\n", filepath.Base(path))
if d.Name() == "Dockerfile" {
dockerfile, err := ioutil.ReadFile(path)
if err != nil {
panic(err)
}
}
}
return err
}
DirEntry 不仅可以返回文件/目录名称,还可以返回目录标志和文件模式以及文件信息,非常方便。
// A DirEntry is an entry read from a directory
// (using the ReadDir function or a ReadDirFile's ReadDir method).
type DirEntry interface {
// Name returns the name of the file (or subdirectory) described by the entry.
// This name is only the final element of the path (the base name), not the entire path.
// For example, Name would return "hello.go" not "/home/gopher/hello.go".
Name() string
// IsDir reports whether the entry describes a directory.
IsDir() bool
// Type returns the type bits for the entry.
// The type bits are a subset of the usual FileMode bits, those returned by the FileMode.Type method.
Type() FileMode
// Info returns the FileInfo for the file or subdirectory described by the entry.
// The returned FileInfo may be from the time of the original directory read
// or from the time of the call to Info. If the file has been removed or renamed
// since the directory read, Info may return an error satisfying errors.Is(err, ErrNotExist).
// If the entry denotes a symbolic link, Info reports the information about the link itself,
// not the link's target.
Info() (FileInfo, error)
}
执行结果
Base: go.mod
Base: main.go
Base: activator_test.go
Base: httpoptions_test.go
Base: test_images.go
Base: apps.go
Base: command.go
Base: helm.go
Base: kubectl.go
Base: shared.go
Base: system.go
Base: kafka_test.go
Base: .dockerignore
Base: .gitignore
Base: Dockerfile
只要有熟悉的 ioutil.ReadFile() 和 json.Unmarshall 函数,文件操作应该就很容易了。