Created
February 11, 2026 05:58
-
-
Save podhmo/4e04e76bc803727d32629d051163a547 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "flag" | |
| "fmt" | |
| "os" | |
| "path/filepath" | |
| "runtime" | |
| "strings" | |
| ) | |
| var ( | |
| wslOutput = flag.Bool("wsl", false, "出力をWSL形式 (/mnt/c/...) に変換") | |
| filter = flag.String("f", "", "Program Files検索時のディレクトリパスフィルタ(contains, case-insensitive)") | |
| ) | |
| func nativeToOutput(path string) string { | |
| if !*wslOutput { | |
| // WSL実行時はWindows形式に戻す | |
| if runtime.GOOS == "linux" { | |
| if len(path) >= 6 && strings.HasPrefix(path, "/mnt/") && path[5] == '/' { | |
| drive := strings.ToUpper(string(path[4])) | |
| rest := strings.ReplaceAll(path[6:], "/", "\\") | |
| return drive + ":\\" + rest | |
| } | |
| } | |
| return path | |
| } | |
| // WSL形式に変換(Windows実行時のみ必要) | |
| if runtime.GOOS == "windows" { | |
| vol := filepath.VolumeName(path) | |
| if vol == "" { | |
| return path | |
| } | |
| drive := strings.ToLower(string(vol[0])) | |
| rest := strings.ReplaceAll(path[len(vol):], "\\", "/") | |
| rest = strings.TrimLeft(rest, "\\/") | |
| return "/mnt/" + drive + "/" + rest | |
| } | |
| return path // 既にWSL形式 | |
| } | |
| func searchInPATH(command string) ([]string, error) { | |
| if command == "" { | |
| return nil, nil | |
| } | |
| pathEnv := os.Getenv("PATH") | |
| if pathEnv == "" { | |
| return nil, fmt.Errorf("PATH環境変数が空です") | |
| } | |
| exeName := command | |
| if !strings.HasSuffix(strings.ToLower(command), ".exe") { | |
| exeName = command + ".exe" | |
| } | |
| sep := string(os.PathListSeparator) | |
| dirs := strings.Split(pathEnv, sep) | |
| var found []string | |
| seen := make(map[string]bool) | |
| for _, d := range dirs { | |
| d = strings.TrimSpace(d) | |
| if d == "" { | |
| continue | |
| } | |
| for _, name := range []string{exeName, command} { | |
| full := filepath.Join(d, name) | |
| if info, err := os.Stat(full); err == nil && !info.IsDir() { | |
| outPath := nativeToOutput(full) | |
| if !seen[outPath] { | |
| seen[outPath] = true | |
| found = append(found, outPath) | |
| } | |
| } | |
| } | |
| } | |
| return found, nil | |
| } | |
| func getProgramFilesRoots() []string { | |
| var candidates []string | |
| if runtime.GOOS == "windows" { | |
| candidates = []string{ | |
| `C:\Program Files`, | |
| `C:\Program Files (x86)`, | |
| } | |
| } else { | |
| candidates = []string{ | |
| "/mnt/c/Program Files", | |
| "/mnt/c/Program Files (x86)", | |
| } | |
| } | |
| var roots []string | |
| for _, c := range candidates { | |
| if info, err := os.Stat(c); err == nil && info.IsDir() { | |
| roots = append(roots, c) | |
| } | |
| } | |
| return roots | |
| } | |
| func findInProgramFiles(command, dirFilter string) ([]string, error) { | |
| roots := getProgramFilesRoots() | |
| if len(roots) == 0 { | |
| return nil, fmt.Errorf("Program Files ディレクトリが見つかりません") | |
| } | |
| var results []string | |
| lowerFilter := strings.ToLower(dirFilter) | |
| baseCommand := strings.TrimSuffix(command, ".exe") | |
| baseCommandLower := strings.ToLower(baseCommand) | |
| for _, root := range roots { | |
| err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error { | |
| if err != nil { | |
| if os.IsPermission(err) { | |
| return filepath.SkipDir | |
| } | |
| fmt.Fprintf(os.Stderr, "警告: %s をスキップ: %v\n", path, err) | |
| return nil | |
| } | |
| // ディレクトリの場合:ルート自身は必ず探索、サブディレクトリのみフィルタ適用 | |
| if info.IsDir() { | |
| if path != root && dirFilter != "" && !strings.Contains(strings.ToLower(path), lowerFilter) { | |
| return filepath.SkipDir | |
| } | |
| return nil | |
| } | |
| // ファイルの場合:.exe で、コマンド名に一致(拡張子あり/なし両対応) | |
| if strings.HasSuffix(strings.ToLower(info.Name()), ".exe") { | |
| nameLower := strings.ToLower(info.Name()) | |
| if strings.EqualFold(info.Name(), command) || // 完全一致(firefox.exe) | |
| strings.EqualFold(info.Name(), baseCommand+".exe") || // firefox + .exe | |
| strings.HasPrefix(nameLower, baseCommandLower) { // firefoxで始まるもの(アップデーターなども含むが実用的) | |
| results = append(results, nativeToOutput(path)) | |
| } | |
| } | |
| return nil | |
| }) | |
| if err != nil { | |
| fmt.Fprintf(os.Stderr, "エラー (%s): %v\n", root, err) | |
| } | |
| } | |
| return results, nil | |
| } | |
| func main() { | |
| flag.Parse() | |
| if len(flag.Args()) == 0 { | |
| fmt.Println("使い方: go run main.go [-f フィルタ] <コマンド名> [-wsl]") | |
| fmt.Println("例:") | |
| fmt.Println(" go run main.go firefox.exe") | |
| fmt.Println(" go run main.go -f firefox firefox.exe -wsl") | |
| fmt.Println(" go run main.go -f \"Mozilla Firefox\" firefox.exe") | |
| return | |
| } | |
| command := flag.Args()[0] | |
| var allResults []string | |
| seen := make(map[string]bool) | |
| // 1. PATH検索(常に優先) | |
| pathResults, err := searchInPATH(command) | |
| if err != nil { | |
| fmt.Printf("PATH検索エラー: %v\n", err) | |
| } else if len(pathResults) > 0 { | |
| fmt.Println("=== PATH から見つかった ===") | |
| for _, p := range pathResults { | |
| if !seen[p] { | |
| seen[p] = true | |
| allResults = append(allResults, p) | |
| fmt.Println(p) | |
| } | |
| } | |
| fmt.Println() | |
| } | |
| // 2. Program Files検索(-f 指定時のみ) | |
| if *filter != "" { | |
| pfResults, err := findInProgramFiles(command, *filter) | |
| if err != nil { | |
| fmt.Printf("Program Files検索エラー: %v\n", err) | |
| } else if len(pfResults) > 0 { | |
| fmt.Printf("=== Program Files から見つかった(ディレクトリパスに \"%s\" を含む)===\n", *filter) | |
| for _, p := range pfResults { | |
| if !seen[p] { | |
| seen[p] = true | |
| allResults = append(allResults, p) | |
| fmt.Println(p) | |
| } | |
| } | |
| } else { | |
| fmt.Printf("Program Files内に \"%s\" を含むディレクトリで %s が見つかりませんでした。\n", *filter, command) | |
| } | |
| } else if len(pathResults) == 0 { | |
| fmt.Println("ヒント: PATHに見つからない場合、-f <文字列> を指定して Program Files を絞り込んで検索できます。") | |
| } | |
| if len(allResults) == 0 { | |
| fmt.Printf("%s が見つかりませんでした。\n", command) | |
| } | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
使いやすくはない。