github.com/goki/ki@v1.1.11/dirs/dirs.go (about) 1 // Copyright (c) 2018, The GoKi Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package dirs provides various utility functions in dealing with directories 6 // such as a list of all the files with a given (set of) extensions and 7 // finding paths within the Go source directory (GOPATH, etc) 8 package dirs 9 10 import ( 11 "fmt" 12 "go/build" 13 "io/ioutil" 14 "os" 15 "path/filepath" 16 "sort" 17 "strings" 18 "time" 19 ) 20 21 // GoSrcDir tries to locate dir in GOPATH/src/ or GOROOT/src/pkg/ and returns its 22 // full path. GOPATH may contain a list of paths. From Robin Elkind github.com/mewkiz/pkg 23 func GoSrcDir(dir string) (absDir string, err error) { 24 for _, srcDir := range build.Default.SrcDirs() { 25 absDir = filepath.Join(srcDir, dir) 26 finfo, err := os.Stat(absDir) 27 if err == nil && finfo.IsDir() { 28 return absDir, nil 29 } 30 } 31 /* this is probably redundant and not needed -- and UserHomeDir is only in 1.12 32 home, err := os.UserHomeDir() 33 if err != nil { 34 return "", err 35 } 36 absDir = filepath.Join(filepath.Join(filepath.Join(home, "go"), "src"), dir) 37 finfo, err := os.Stat(absDir) 38 if err == nil && finfo.IsDir() { 39 return absDir, nil 40 } 41 */ 42 return "", fmt.Errorf("kit.GoSrcDir: unable to locate directory (%q) in GOPATH/src/ (%q) or GOROOT/src/pkg/ (%q)", dir, os.Getenv("GOPATH"), os.Getenv("GOROOT")) 43 } 44 45 // ExtFiles returns all the FileInfo's for files with given extension(s) in directory 46 // in sorted order (if exts is empty then all files are returned). 47 // In case of error, returns nil. 48 func ExtFiles(path string, exts []string) []os.FileInfo { 49 files, err := ioutil.ReadDir(path) 50 if err != nil { 51 return nil 52 } 53 if len(exts) == 0 { 54 return files 55 } 56 sz := len(files) 57 if sz == 0 { 58 return nil 59 } 60 for i := sz - 1; i >= 0; i-- { 61 fn := files[i] 62 ext := filepath.Ext(fn.Name()) 63 keep := false 64 for _, ex := range exts { 65 if strings.EqualFold(ext, ex) { 66 keep = true 67 break 68 } 69 } 70 if !keep { 71 files = append(files[:i], files[i+1:]...) 72 } 73 } 74 return files 75 } 76 77 // ExtFileNames returns all the file names with given extension(s) in directory 78 // in sorted order (if exts is empty then all files are returned) 79 func ExtFileNames(path string, exts []string) []string { 80 f, err := os.Open(path) 81 if err != nil { 82 return nil 83 } 84 files, err := f.Readdirnames(-1) 85 f.Close() 86 if err != nil { 87 return nil 88 } 89 if len(exts) == 0 { 90 sort.StringSlice(files).Sort() 91 return files 92 } 93 sz := len(files) 94 if sz == 0 { 95 return nil 96 } 97 for i := sz - 1; i >= 0; i-- { 98 fn := files[i] 99 ext := filepath.Ext(fn) 100 keep := false 101 for _, ex := range exts { 102 if strings.EqualFold(ext, ex) { 103 keep = true 104 break 105 } 106 } 107 if !keep { 108 files = append(files[:i], files[i+1:]...) 109 } 110 } 111 sort.StringSlice(files).Sort() 112 return files 113 } 114 115 // Dirs returns a slice of all the directories within a given directory 116 func Dirs(path string) []string { 117 files, err := ioutil.ReadDir(path) 118 if err != nil { 119 return nil 120 } 121 122 var fnms []string 123 for _, fi := range files { 124 if fi.IsDir() { 125 fnms = append(fnms, fi.Name()) 126 } 127 } 128 return fnms 129 } 130 131 // LatestMod returns the latest (most recent) modification time for any of the 132 // files in the directory (optionally filtered by extension(s) if exts != nil) 133 // if no files or error, returns zero time value 134 func LatestMod(path string, exts []string) time.Time { 135 tm := time.Time{} 136 files := ExtFiles(path, exts) 137 if len(files) == 0 { 138 return tm 139 } 140 for _, fi := range files { 141 if fi.ModTime().After(tm) { 142 tm = fi.ModTime() 143 } 144 } 145 return tm 146 } 147 148 // AllFiles returns a slice of all the files, recursively, within a given directory 149 // Due to the nature of the filepath.Walk function, the first entry will be the 150 // directory itself, for reference -- just skip past that if you don't need it. 151 func AllFiles(path string) ([]string, error) { 152 var fnms []string 153 er := filepath.Walk(path, func(path string, info os.FileInfo, err error) error { 154 if err != nil { 155 return err 156 } 157 fnms = append(fnms, path) 158 return nil 159 }) 160 return fnms, er 161 } 162 163 // HasFile returns true if given directory has given file (exact match) 164 func HasFile(path, file string) bool { 165 files, err := ioutil.ReadDir(path) 166 if err != nil { 167 return false 168 } 169 for _, fn := range files { 170 if fn.Name() == file { 171 return true 172 } 173 } 174 return false 175 } 176 177 // note: rejected from std lib, but often need: https://github.com/golang/go/issues/25012 178 // https://github.com/golang/go/issues/5366 179 180 // SplitExt returns the base of the file name without extension, and the extension 181 func SplitExt(fname string) (fbase, ext string) { 182 ext = filepath.Ext(fname) 183 fbase = strings.TrimSuffix(fname, ext) 184 return 185 }