57 lines
1.2 KiB
Go
57 lines
1.2 KiB
Go
package xexec
|
|
|
|
import (
|
|
"errors"
|
|
"io/fs"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
// findExecutable is from package exec
|
|
func findExecutable(file string) error {
|
|
d, err := os.Stat(file)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if m := d.Mode(); !m.IsDir() && m&0111 != 0 {
|
|
return nil
|
|
}
|
|
return fs.ErrPermission
|
|
}
|
|
|
|
// SearchPath searches for all executables that have prefix in their names in
|
|
// the directories named by the PATH environment variable.
|
|
func SearchPath(prefix string) ([]string, error) {
|
|
var matches []string
|
|
envPath := os.Getenv("PATH")
|
|
dirSet := make(map[string]struct{})
|
|
for _, dir := range filepath.SplitList(envPath) {
|
|
if dir == "" {
|
|
// From exec package:
|
|
// Unix shell semantics: path element "" means "."
|
|
dir = "."
|
|
}
|
|
if _, ok := dirSet[dir]; ok {
|
|
continue
|
|
}
|
|
dirSet[dir] = struct{}{}
|
|
files, err := os.ReadDir(dir)
|
|
if err != nil {
|
|
if errors.Is(err, fs.ErrNotExist) {
|
|
continue
|
|
}
|
|
return nil, err
|
|
}
|
|
for _, f := range files {
|
|
if strings.HasPrefix(f.Name(), prefix) {
|
|
match := filepath.Join(dir, f.Name())
|
|
if err := findExecutable(match); err == nil {
|
|
matches = append(matches, match)
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
return matches, nil
|
|
}
|