Golang: Walk Directory

By Xah Lee. Date: . Last updated: .

to go thru all files and directory, use

filepath.Walk(dir_path, process_func)

from package path/filepath

package main

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

var myDir = "/Users/x/web/"

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

func main() {
	// the function that handles each file or dir
	var ff = func(pathX string, infoX os.FileInfo, errX error) error {

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

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

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

		return nil
	}

	err := filepath.Walk(myDir, ff)

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

filepath.Walk(dir_path, ff) walks dir_path, for each file or dir, it calls ff

when there's a problem, a error is passed to ff. ff can do whatever with it.

ff must return one of:

nil
Normal.
filepath.SkipDir
If ff returns filepath.SkipDir, then filepath.Walk will skip. 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 ff returns a error, then filepath.Walk returns a error. The walk is stopped

Argument Passed to the Walker Function

filepath.Walk(myDir, ff) passes 3 arguments to ff.

ff is the walker function that you must write. It process each path.

The arguments passed to the walker are:

arg1 string
This is the full path of current file or directory.
arg2 os.FileInfo
This is a value that implements the os.FileInfo interface. It contain info about the file. Example: arg2.IsDir() to check if it's dir or file. arg2.Size() to get file size.
arg3 error.
If there's a error, it's passed to your walker function.

In your walker function, you must delare the types accordingly. example:

var walker = func(pathX string, infoX os.FileInfo, errX error) error {}

FileInfo

A FileInfo is a interface that has methods of a file.

type FileInfo interface {
    Name() string       // base name of the file
    Size() int64        // length in bytes for regular files; system-dependent for others
    Mode() FileMode     // file mode bits
    ModTime() time.Time // modification time
    IsDir() bool        // abbreviation for Mode().IsDir()
    Sys() interface{}   // underlying data source (can return nil)
}

error

The error built-in interface type is the conventional interface for representing an error condition, with the nil value representing no error.

type error interface {
    Error() string
}

Alternative

there is a well known problem that filepath.Walk is slow, not implemented optimally.

see https://github.com/golang/go/issues/16399

here's alternative: https://github.com/karrick/godirwalk/blob/master/README.md

If you have a question, put $5 at patreon and message me.

Golang

Examples

Reference