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

}


更多教程: