github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/utils/fileutils/fileutils.go (about)

     1  package fileutils
     2  
     3  import (
     4  	"os"
     5  	"path/filepath"
     6  )
     7  
     8  var (
     9  	commonBaseSearchPaths = []string{
    10  		".",
    11  		"..",
    12  		"../..",
    13  		"../../..",
    14  	}
    15  )
    16  
    17  func findPath(path string, baseSearchPaths []string, workingDirFirst bool, filter func(os.FileInfo) bool) string {
    18  	if filepath.IsAbs(path) {
    19  		if _, err := os.Stat(path); err == nil {
    20  			return path
    21  		}
    22  
    23  		return ""
    24  	}
    25  
    26  	searchPaths := []string{}
    27  	if workingDirFirst {
    28  		searchPaths = append(searchPaths, baseSearchPaths...)
    29  	}
    30  
    31  	// Attempt to search relative to the location of the running binary either before
    32  	// or after searching relative to the working directory, depending on `workingDirFirst`.
    33  	var binaryDir string
    34  	if exe, err := os.Executable(); err == nil {
    35  		if exe, err = filepath.EvalSymlinks(exe); err == nil {
    36  			if exe, err = filepath.Abs(exe); err == nil {
    37  				binaryDir = filepath.Dir(exe)
    38  			}
    39  		}
    40  	}
    41  	if binaryDir != "" {
    42  		for _, baseSearchPath := range baseSearchPaths {
    43  			searchPaths = append(
    44  				searchPaths,
    45  				filepath.Join(binaryDir, baseSearchPath),
    46  			)
    47  		}
    48  	}
    49  
    50  	if !workingDirFirst {
    51  		searchPaths = append(searchPaths, baseSearchPaths...)
    52  	}
    53  
    54  	for _, parent := range searchPaths {
    55  		found, err := filepath.Abs(filepath.Join(parent, path))
    56  		if err != nil {
    57  			continue
    58  		} else if fileInfo, err := os.Stat(found); err == nil {
    59  			if filter != nil {
    60  				if filter(fileInfo) {
    61  					return found
    62  				}
    63  			} else {
    64  				return found
    65  			}
    66  		}
    67  	}
    68  
    69  	return ""
    70  }
    71  
    72  func FindPath(path string, baseSearchPaths []string, filter func(os.FileInfo) bool) string {
    73  	return findPath(path, baseSearchPaths, true, filter)
    74  }
    75  
    76  // FindFile looks for the given file in nearby ancestors relative to the current working
    77  // directory as well as the directory of the executable.
    78  func FindFile(path string) string {
    79  	return FindPath(path, commonBaseSearchPaths, func(fileInfo os.FileInfo) bool {
    80  		return !fileInfo.IsDir()
    81  	})
    82  }
    83  
    84  // fileutils.FindDir looks for the given directory in nearby ancestors relative to the current working
    85  // directory as well as the directory of the executable, falling back to `./` if not found.
    86  func FindDir(dir string) (string, bool) {
    87  	found := FindPath(dir, commonBaseSearchPaths, func(fileInfo os.FileInfo) bool {
    88  		return fileInfo.IsDir()
    89  	})
    90  	if found == "" {
    91  		return "./", false
    92  	}
    93  
    94  	return found, true
    95  }
    96  
    97  // FindDirRelBinary looks for the given directory in nearby ancestors relative to the
    98  // directory of the executable, then relative to the working directory, falling back to `./` if not found.
    99  func FindDirRelBinary(dir string) (string, bool) {
   100  	found := findPath(dir, commonBaseSearchPaths, false, func(fileInfo os.FileInfo) bool {
   101  		return fileInfo.IsDir()
   102  	})
   103  	if found == "" {
   104  		return "./", false
   105  	}
   106  	return found, true
   107  }