gopkg.in/tools/godep.v67@v67.0.0-20160513230433-2d182dfe781d/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 }