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 }