使用Go列出文件夹中的文件

骑驴找蚂蚁 · 2021年03月11日 · 阅读 168

在本文中,我解释了如何使用Go获取文件系统上的文件夹内的文件列表,该任务也称为树遍历。 

您可以根据自己的目标使用两个方便的stdlib函数。

我列出了3种方法: filepath.Walk, ioutil.ReadDiros.File.Readdir.

1. filepath.Walk

path/filepath stdlib软件包提供了便捷的Walk功能。 但是它会自动扫描子目录,因此您需确保这是您想要的。

用法很简单:

package main

import (
    "fmt"
    "os"
    "path/filepath"
)

func main() {
    var files []string

    root := "/some/folder/to/scan"
    err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
        files = append(files, path)
        return nil
    })
    if err != nil {
        panic(err)
    }
    for _, file := range files {
        fmt.Println(file)
    }
}

filepath.Walk接受指向根文件夹的字符串和WalkFunc(具有签名的函数类型),每次扫描文件夹都会调用此函数。

os.FileInfo类型的info变量很重要,因为我们可以获得有关当前文件的许多信息:名称,大小,模式,修改时间(如果它是文件夹或文件)以及基础数据。

例如,我们可以通过添加来避免处理文件夹.

if info.IsDir() {
    return nil
}

通过使用filepath.Ext并传递文件路径,可以基于文件的扩展名将文件排除(或包括)到切片中:

if filepath.Ext(path) == ".dat" {
    return nil
}

我们可以使用以下命令存储文件名而不是文件路径

files = append(files, info.Name())

我们还可以在单​​独的闭包中定义WalkFunc。 我们只需要传递一个指向访问文件的指针:

package main

import (
    "fmt"
    "log"
    "os"
    "path/filepath"
)

func visit(files *[]string) filepath.WalkFunc {
    return func(path string, info os.FileInfo, err error) error {
        if err != nil {
            log.Fatal(err)
        }
        *files = append(*files, path)
        return nil
    }
}

func main() {
    var files []string

    root := "/some/folder/to/scan"
    err := filepath.Walk(root, visit(&files))
    if err != nil {
        panic(err)
    }
    for _, file := range files {
        fmt.Println(file)
    }
}

2. ioutil.ReadDir

filepath.Walk很方便,但默认情况下也扫描子文件夹,这可能不是您想要的。

Go标准库还提供ioutil.ReadDir.

func ReadDir(dirname string) ([]os.FileInfo, error)

ReadDir读取以dirname命名的目录,并返回按文件名排序的目录条目的列表。

这是文档中的一个示例。 ioutil.ReadDir将文件夹路径作为字符串,并返回上面描述的os.FileInfo的一部分。

package main

import (
    "fmt"
    "io/ioutil"
    "log"
)

func main() {
    files, err := ioutil.ReadDir(".")
    if err != nil {
        log.Fatal(err)
    }

    for _, file := range files {
        fmt.Println(file.Name())
    }
}

3. os.File.Readdir

在标准备库内部,ioutil.ReadDir被实现为

// ReadDir reads the directory named by dirname and returns
// a list of directory entries sorted by filename.
func ReadDir(dirname string) ([]os.FileInfo, error) {
    f, err := os.Open(dirname)
    if err != nil {
        return nil, err
    }
    list, err := f.Readdir(-1)
    f.Close()
    if err != nil {
        return nil, err
    }
    sort.Slice(list, func(i, j int) bool { return list[i].Name() < list[j].Name() })
    return list, nil
}

看代码得知,它会扫描目录名并按名称对文件进行排序。 如果您不需要排序,也可以使用

package main

import (
    "fmt"
    "log"
    "os"
)

func main() {
    dirname := "."

    f, err := os.Open(dirname)
    if err != nil {
        log.Fatal(err)
    }
    files, err := f.Readdir(-1)
    f.Close()
    if err != nil {
        log.Fatal(err)
    }

    for _, file := range files {
        fmt.Println(file.Name())
    }
}

以上就是golang中获取文件夹文件的三种用法.

关于作者

全栈工程师

文章被阅读 136.5k
获赞 11