gopkg.in/tools/godep.v56@v56.0.0-20160226230103-b32db8cfcaad/Godeps/_workspace/src/github.com/kr/fs/walk.go (about)

     1  // Package fs provides filesystem-related functions.
     2  package fs
     3  
     4  import (
     5  	"os"
     6  )
     7  
     8  // Walker provides a convenient interface for iterating over the
     9  // descendants of a filesystem path.
    10  // Successive calls to the Step method will step through each
    11  // file or directory in the tree, including the root. The files
    12  // are walked in lexical order, which makes the output deterministic
    13  // but means that for very large directories Walker can be inefficient.
    14  // Walker does not follow symbolic links.
    15  type Walker struct {
    16  	fs      FileSystem
    17  	cur     item
    18  	stack   []item
    19  	descend bool
    20  }
    21  
    22  type item struct {
    23  	path string
    24  	info os.FileInfo
    25  	err  error
    26  }
    27  
    28  // Walk returns a new Walker rooted at root.
    29  func Walk(root string) *Walker {
    30  	return WalkFS(root, new(fs))
    31  }
    32  
    33  // WalkFS returns a new Walker rooted at root on the FileSystem fs.
    34  func WalkFS(root string, fs FileSystem) *Walker {
    35  	info, err := fs.Lstat(root)
    36  	return &Walker{
    37  		fs:    fs,
    38  		stack: []item{{root, info, err}},
    39  	}
    40  }
    41  
    42  // Step advances the Walker to the next file or directory,
    43  // which will then be available through the Path, Stat,
    44  // and Err methods.
    45  // It returns false when the walk stops at the end of the tree.
    46  func (w *Walker) Step() bool {
    47  	if w.descend && w.cur.err == nil && w.cur.info.IsDir() {
    48  		list, err := w.fs.ReadDir(w.cur.path)
    49  		if err != nil {
    50  			w.cur.err = err
    51  			w.stack = append(w.stack, w.cur)
    52  		} else {
    53  			for i := len(list) - 1; i >= 0; i-- {
    54  				path := w.fs.Join(w.cur.path, list[i].Name())
    55  				w.stack = append(w.stack, item{path, list[i], nil})
    56  			}
    57  		}
    58  	}
    59  
    60  	if len(w.stack) == 0 {
    61  		return false
    62  	}
    63  	i := len(w.stack) - 1
    64  	w.cur = w.stack[i]
    65  	w.stack = w.stack[:i]
    66  	w.descend = true
    67  	return true
    68  }
    69  
    70  // Path returns the path to the most recent file or directory
    71  // visited by a call to Step. It contains the argument to Walk
    72  // as a prefix; that is, if Walk is called with "dir", which is
    73  // a directory containing the file "a", Path will return "dir/a".
    74  func (w *Walker) Path() string {
    75  	return w.cur.path
    76  }
    77  
    78  // Stat returns info for the most recent file or directory
    79  // visited by a call to Step.
    80  func (w *Walker) Stat() os.FileInfo {
    81  	return w.cur.info
    82  }
    83  
    84  // Err returns the error, if any, for the most recent attempt
    85  // by Step to visit a file or directory. If a directory has
    86  // an error, w will not descend into that directory.
    87  func (w *Walker) Err() error {
    88  	return w.cur.err
    89  }
    90  
    91  // SkipDir causes the currently visited directory to be skipped.
    92  // If w is not on a directory, SkipDir has no effect.
    93  func (w *Walker) SkipDir() {
    94  	w.descend = false
    95  }