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

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

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

我列出了3种方法:filepath.Walkioutil.ReadDir或者os.File.Readdir

使用filepath.Walk

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

用法很简单:

package main

import ( “fmt” “os” “path/filepath” )

func main() { var files []string

<span style="color:#a6e22e">root</span> <span style="color:#f92672">:=</span> <span style="color:#e6db74">"/some/folder/to/scan"</span>
<span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">filepath</span>.<span style="color:#a6e22e">Walk</span>(<span style="color:#a6e22e">root</span>, <span style="color:#66d9ef">func</span>(<span style="color:#a6e22e">path</span> <span style="color:#66d9ef">string</span>, <span style="color:#a6e22e">info</span> <span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">FileInfo</span>, <span style="color:#a6e22e">err</span> <span style="color:#66d9ef">error</span>) <span style="color:#66d9ef">error</span> {
    <span style="color:#a6e22e">files</span> = append(<span style="color:#a6e22e">files</span>, <span style="color:#a6e22e">path</span>)
    <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nil</span>
})
<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
    panic(<span style="color:#a6e22e">err</span>)
}
<span style="color:#66d9ef">for</span> <span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">file</span> <span style="color:#f92672">:=</span> <span style="color:#66d9ef">range</span> <span style="color:#a6e22e">files</span> {
    <span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#a6e22e">file</span>)
}

}

filepath.Walk接受指向根文件夹的字符串,以及一个WalkFunc,带签名的函数类型

type WalkFunc func(path string, info os.FileInfo, err error) error

文件夹扫描的每次迭代都会调用此函数。

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

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

if info.IsDir() {
    return nil
}

您可以根据扩展名将文件排除(或包括)到切片中,方法是使用filepath.Ext并传递文件路径:

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

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

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

我们还可以定义WalkFunc在一个单独的关闭。我们只需要传递一个指向filesvisit

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

<span style="color:#a6e22e">root</span> <span style="color:#f92672">:=</span> <span style="color:#e6db74">"/some/folder/to/scan"</span>
<span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">filepath</span>.<span style="color:#a6e22e">Walk</span>(<span style="color:#a6e22e">root</span>, <span style="color:#a6e22e">visit</span>(<span style="color:#f92672">&amp;</span><span style="color:#a6e22e">files</span>))
<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
    panic(<span style="color:#a6e22e">err</span>)
}
<span style="color:#66d9ef">for</span> <span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">file</span> <span style="color:#f92672">:=</span> <span style="color:#66d9ef">range</span> <span style="color:#a6e22e">files</span> {
    <span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#a6e22e">file</span>)
}

}

使用ioutil.ReadDir

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

Go stdlib还提供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) }

<span style="color:#66d9ef">for</span> <span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">file</span> <span style="color:#f92672">:=</span> <span style="color:#66d9ef">range</span> <span style="color:#a6e22e">files</span> {
    <span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#a6e22e">file</span>.<span style="color:#a6e22e">Name</span>())
}

}

使用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
}

如您所见,它会扫描dirname并按名称对文件进行排序。如果您不需要排序,也可以使用

package main

import ( “fmt” “log” “os” )

func main() { dirname := “.”

<span style="color:#a6e22e">f</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">Open</span>(<span style="color:#a6e22e">dirname</span>)
<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
    <span style="color:#a6e22e">log</span>.<span style="color:#a6e22e">Fatal</span>(<span style="color:#a6e22e">err</span>)
}
<span style="color:#a6e22e">files</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">f</span>.<span style="color:#a6e22e">Readdir</span>(<span style="color:#f92672">-</span><span style="color:#ae81ff">1</span>)
<span style="color:#a6e22e">f</span>.<span style="color:#a6e22e">Close</span>()
<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
    <span style="color:#a6e22e">log</span>.<span style="color:#a6e22e">Fatal</span>(<span style="color:#a6e22e">err</span>)
}

<span style="color:#66d9ef">for</span> <span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">file</span> <span style="color:#f92672">:=</span> <span style="color:#66d9ef">range</span> <span style="color:#a6e22e">files</span> {
    <span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#a6e22e">file</span>.<span style="color:#a6e22e">Name</span>())
}

}


更多教程: