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 函数,文件操作应该就很容易了。

广告
将在 10 秒后关闭
bannerAds