How to list the files in a directory with Go
The Go standard library provides several packages for working with files and directories. This article examines some of the ways you can fetch a list of all the files in a directory using stdlib methods.
Let’s consider four ways to retrieve a list of files in a directory with Go. They’re all different in subtle ways so the method you’ll end up choosing will ultimately depend on what you’re trying to achieve.
Using ioutil.ReadDir
The ioutil.ReadDir
method takes a directory name as its only argument, and returns a slice of directory entries sorted by name. The resulting slice contains os.FileInfo
types, which provide the methods listed here. You can loop over the returned slice to access each individual entry.
Here’s an example that lists all the files in the current directory:
package main
import (
"fmt"
"io/ioutil"
"log"
)
func main() {
files, err := ioutil.ReadDir(".")
if err != nil {
log.Fatal(err)
}
for _, f := range files {
fmt.Println(f.Name())
}
}
Using filepath.Walk
The above method of accessing files is great if you do not need to scan sub-directories. Otherwise, it may not meet your needs and that’s when the filepath.Walk
method may come in handy.
It accepts a root directory name and a WalkFunc
function type with the signature shown below. This function is called for each file or directory in the tree, including the root.
type WalkFunc func(path string, info os.FileInfo, err error) error
Here’s how to use filepath.Walk
to print out all the files in a directory including all sub-directories:
package main
import (
"fmt"
"log"
"os"
"path/filepath"
)
func main() {
err := filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
fmt.Println(path)
return nil
})
if err != nil {
log.Println(err)
}
}
As you can see from the screenshot below, the contents of the counter
directory is printed unlike when we employed ioutil.ReadDir
above.
It is important to note that filepath.Walk
will not follow symbolic links and can be inefficient for really large directories.
Using os.File.Readdir
The ioutil.ReadDir
method actually uses the Readdir
method of os.File
to scan the directory, and then sorts the slice afterwards by name. If you don’t need the results to be sorted, you can speed things up a bit by using the os.File.Readdir
method directly as shown below:
package main
import (
"fmt"
"log"
"os"
)
func main() {
file, err := os.Open(".")
if err != nil {
log.Fatal(err)
}
defer file.Close()
list, err := file.Readdir(-1)
if err != nil {
log.Fatal(err)
}
for _, f := range list {
fmt.Println(f.Name())
}
}
Using os.File.Readdirnames
If all you need is the names of the files without all the extra information that the above methods provide, you can use os.File.Readdirnames
which takes an integer (n
) and reads at most n
names.
If n
is zero or less, all the names in the directory will be returned in a single slice. Here’s an example:
package main
import (
"fmt"
"log"
"os"
)
func main() {
file, err := os.Open(".")
if err != nil {
log.Fatal(err)
}
defer file.Close()
names, err := file.Readdirnames(0)
if err != nil {
log.Fatal(err)
}
for _, v := range names {
fmt.Println(v)
}
}
Conclusion
As you can see, listing files in a directory is a trivial task in Go and can be done in many ways. If you know of another method that is not covered above, please share it in the comments.
Thanks for reading, and happy coding!