Golang: Walk Directory, List Files

By Xah Lee. Date: . Last updated: .

Functions to Traverse a Directory

Golang has 3 different functions to walk a directory.

path/filepath.Walk

introduced in go version 1 (2012).

https://pkg.go.dev/path/filepath#Walk

💡 TIP: Slow. Don't use this.

path/filepath.WalkDir

new in go version 1.16. (2021)

https://pkg.go.dev/path/filepath#WalkDir

💡 TIP: I recommend this.

filepath.WalkDir(dirPath, doF)

it walks dirPath, for each file or dir, it calls doF

doF is a function of type fs.WalkDirFunc you need to define. It do something for each file.

os/fs.WalkDir

new in go version 1.16, part of the new abstract file system.

the doF Function (type WalkFunc)

The spec for type WalkFunc is this:

var doF = func(xpath string, xinfo fs.DirEntry, xerr error) error {body}

The arguments passed to the doF are:

xpath (type string)

the full path of current file or directory.

xinfo (type fs.DirEntry)

A fs.DirEntry object. It contain info about the file.

e.g. use it like this: xinfo.IsDir().

https://pkg.go.dev/io/fs#FileInfo

xerr (type error)

If there's a error.

https://pkg.go.dev/path/filepath#WalkFunc

Return Value of Process File Function

When there's a problem, a error is passed to doF. The function doF can do whatever with it.

doF must return one of:

nil

Normal.

filepath.SkipDir

If doF returns filepath.SkipDir, then filepath.WalkDir will skip it. Meaning: If current path is dir, skip it, but if current path is a file, then skip rest of files in the directory

value of type error

(error is a interface) If doF returns a error, then filepath.WalkDir returns a error. The walk is stopped

Sample Code to Walk a Dir

package main

import (
	"fmt"
	"io/fs"
	"path/filepath"
)

var xDir = "c:/Users/xah/web/xahlee_info/js/"

// go thru a dir and print all file name and extension

func main() {

	var doF = func(xpath string, xinfo fs.DirEntry, xerr error) error {

		// first thing to do, check error. and decide what to do about it
		if xerr != nil {
			fmt.Printf("error [%v] at a path [%q]\n", xerr, xpath)
			return xerr
		}

		fmt.Printf("xpath: %v\n", xpath)

		// find out if it's a dir or file, if file, print info
		if xinfo.IsDir() {
			fmt.Printf("is dir.\n")
		} else {
			fmt.Printf("  dir: [%v]\n", filepath.Dir(xpath))
			fmt.Printf("  file name [%v]\n", xinfo.Name())
			fmt.Printf("  extenion: [%v]\n", filepath.Ext(xpath))
		}

		return nil
	}

	err := filepath.WalkDir(xDir, doF)

	if err != nil {
		fmt.Printf("error walking the path %q: %v\n", xDir, err)
	}
}

Migration tip from filepath.Walk to filepath.WalkDir