DEV Community

Manigandan Dharmalingam
Manigandan Dharmalingam

Posted on

List files in a directory using Golang

#go

We can get a list of files inside a folder on the file system using various Golang standard library functions.

  • filepath.Walk
  • ioutil.ReadDir
  • os.File.Readdir

Source: https://gist.github.com/manigandand/19aa61c81aaabc0962157380e575c006#file-list_directory-go

Using filepath.Walk

The path/filepath package provides a handy way to scan all the files in a directory, it will automatically scan each sub-directories in the directory.

Walk walks the file tree rooted at root, calling walkFn for each file or directory in the tree, including root. All errors that arise visiting files and directories are filtered by walkFn. The files are walked in lexical order, which makes the output deterministic but means that for very large directories Walk can be inefficient. The walk does not follow symbolic links.

package main

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

func main() {
    var root string
    if len(os.Args) == 1 {
        log.Fatal("No path given, Please specify path.")
        return
    }
    if root = os.Args[1]; root == "" {
        log.Fatal("No path given, Please specify path.")
        return
    }
    // filepath.Walk
    files, err := FilePathWalkDir(root)
    if err != nil {
        panic(err)
    }
    for _, file := range files {
        fmt.Println(file)
    }
}

func FilePathWalkDir(root string) ([]string, error) {
    var files []string
    err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
        if !info.IsDir() {
            files = append(files, path)
        }
        return nil
    })
    return files, err
}

Using ioutil.ReadDir

ioutil.ReadDir reads the directory named by dirname and returns a list of directory entries sorted by filename.


func IOReadDir(root string) ([]string, error) {
    var files []string
    fileInfo, err := ioutil.ReadDir(root)
    if err != nil {
        return files, err
    }
    for _, file := range fileInfo {
        files = append(files, file.Name())
    }
    return files, nil
}

Using os.File.Readdir

Readdir reads the contents of the directory associated with the file and returns a slice of up to n FileInfo values, as would be returned by Lstat, in directory order. Subsequent calls on the same file will yield further FileInfos.


func OSReadDir(root string) ([]string, error) {
    var files []string
    f, err := os.Open(root)
    if err != nil {
        return files, err
    }
    fileInfo, err := f.Readdir(-1)
    f.Close()
    if err != nil {
        return files, err
    }
    for _, file := range fileInfo {
        files = append(files, file.Name())
    }
    return files, nil
}

See the benchmark result of these three functions.

benchmark

package main

import (
    "testing"
)

var root string = "/home/manigandan/Desktop/Manigandan/sample"

func BenchmarkFilePathWalkDir1(b *testing.B)  { benchmarkFilePathWalkDir(1, root, b) }
func BenchmarkFilePathWalkDir2(b *testing.B)  { benchmarkFilePathWalkDir(2, root, b) }
func BenchmarkFilePathWalkDir3(b *testing.B)  { benchmarkFilePathWalkDir(3, root, b) }
func BenchmarkFilePathWalkDir10(b *testing.B) { benchmarkFilePathWalkDir(10, root, b) }
func BenchmarkFilePathWalkDir20(b *testing.B) { benchmarkFilePathWalkDir(20, root, b) }
func BenchmarkFilePathWalkDir30(b *testing.B) { benchmarkFilePathWalkDir(30, root, b) }
func BenchmarkFilePathWalkDir40(b *testing.B) { benchmarkFilePathWalkDir(40, root, b) }
func BenchmarkFilePathWalkDir50(b *testing.B) { benchmarkFilePathWalkDir(50, root, b) }
func BenchmarkIOReadDir1(b *testing.B)        { benchmarkIOReadDir(1, root, b) }
func BenchmarkIOReadDir2(b *testing.B)        { benchmarkIOReadDir(2, root, b) }
func BenchmarkIOReadDir3(b *testing.B)        { benchmarkIOReadDir(3, root, b) }
func BenchmarkIOReadDir10(b *testing.B)       { benchmarkIOReadDir(10, root, b) }
func BenchmarkIOReadDir20(b *testing.B)       { benchmarkIOReadDir(20, root, b) }
func BenchmarkIOReadDir30(b *testing.B)       { benchmarkIOReadDir(30, root, b) }
func BenchmarkIOReadDir40(b *testing.B)       { benchmarkIOReadDir(40, root, b) }
func BenchmarkIOReadDir50(b *testing.B)       { benchmarkIOReadDir(50, root, b) }
func BenchmarkOSReadDir1(b *testing.B)        { benchmarkOSReadDir(1, root, b) }
func BenchmarkOSReadDir2(b *testing.B)        { benchmarkOSReadDir(2, root, b) }
func BenchmarkOSReadDir3(b *testing.B)        { benchmarkOSReadDir(3, root, b) }
func BenchmarkOSReadDir10(b *testing.B)       { benchmarkOSReadDir(10, root, b) }
func BenchmarkOSReadDir20(b *testing.B)       { benchmarkOSReadDir(20, root, b) }
func BenchmarkOSReadDir30(b *testing.B)       { benchmarkOSReadDir(30, root, b) }
func BenchmarkOSReadDir40(b *testing.B)       { benchmarkOSReadDir(40, root, b) }
func BenchmarkOSReadDir50(b *testing.B)       { benchmarkOSReadDir(50, root, b) }
func benchmarkFilePathWalkDir(i int, root string, b *testing.B) {
    // run the FilePathWalkDir function b.N times
    for n := 0; n < b.N; n++ {
        FpW(i, root)
    }
}
func benchmarkIOReadDir(i int, root string, b *testing.B) {
    // run the IOReadDir function b.N times
    for n := 0; n < b.N; n++ {
        IoRdir(i, root)
    }
}
func benchmarkOSReadDir(i int, root string, b *testing.B) {
    // run the OSReadDir function b.N times
    for n := 0; n < b.N; n++ {
        OsRdir(i, root)
    }
}

Medium Article

Top comments (1)

Collapse
 
juancarlospaco profile image
Juan Carlos

But in the first solution you included Logging,
its not fair with the other 2 solutions as is doing extra stuff.

import os
for i in walkDir".": echo i
Enter fullscreen mode Exit fullscreen mode

My Nim solution :)