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  }