kurumi-bioの雑記帳

プログラミング、パソコン、ペット、 犬、お出かけ

初心者のGo言語 -30- <LookPath>

こんにちは、kurumi-bioです。
第1回目のexecパッケージ(標準ライブラリー)の学習です。

環境

  • Windows
    OSバージョン:Windows11 Home 22H2
    Go言語のバージョン:go version go1.20 windows/amd64
  • Linux
    OSバージョン:openSUSE Leap 15.4
    Go言語のバージョン:go version go1.20.1 linux/amd64

Variables(変数)

var ErrDot = errors.New("cannot run executable found relative to current directory")

変数の説明ErrDot は、暗黙的または明示的に「.」がパスに含まれているため、パス ルックアップが現在のディレクトリの実行可能ファイルに解決されたことを示します。詳細については、パッケージのドキュメントを参照してください。このパッケージの関数は ErrDot を直接返さないことに注意してください。コードでは、err == ErrDot ではなく、errors.Is(err, ErrDot) を使用して、返されたエラー err がこの状態によるものかどうかをテストする必要があります。

var ErrNotFound = errors.New("executable file not found in $PATH")

変数の説明ErrNotFound は、パス検索で実行可能ファイルが見つからなかった場合に発生するエラーです。

var ErrWaitDelay = errors.New("exec: WaitDelay expired before I/O complete")

変数の説明ErrWaitDelay は、(*Cmd).Wait によって返されます (プロセスが正常なステータス コードで終了したが、コマンドの WaitDelay が期限切れになる前にその出力パイプが閉じられていない場合)。

LookPath関数

func LookPath(file string) (string, error)

変数の説明LookPath は、PATH 環境変数で指定されたディレクトリで file という名前の実行可能ファイルを検索します。ファイルにスラッシュが含まれている場合は、直接試行され、PATH は参照されません。それ以外の場合、成功すると、結果は絶対パスになります。

古いバージョンの Go では、LookPath は現在のディレクトリからの相対パスを返すことができました。 Go 1.19 以降、LookPath は代わりに、errors.Is(err, ErrDot) を満たすエラーと共にそのパスを返します。詳細については、パッケージのドキュメントを参照してください。

◆テストコード

package main

import (
    "fmt"
    "os"
    "os/exec"
)

func main() {
    if len(os.Args) != 2 {
        fmt.Fprintln(os.Stderr, "usage: LookPathTest.exe fileName")
        os.Exit(1)
    }
    s, e := exec.LookPath(os.Args[1])
    if e != nil {
        fmt.Fprintf(os.Stderr, "ERROR=[%v]\n", os.NewSyscallError("os.LookPath", e))
        os.Exit(1)
    } else {
        fmt.Printf("path=[%s]\n", s)
    }
}

コードの説明 実行時の引数で指定したファイルの検索結果を出力します。

◆実行結果(Windows)

実行結果の説明 存在しないファイルを指定すると、executable file not found in %PATH%(%PATH%に実行可能ファイルが見つからない)というエラーが発生しました。

実行結果の説明 goコマンドのファイルを検索するとパスが戻ってきました。実際に存在するファイル名はgo.exeですが、goでも同じ結果になりました。

実行結果の説明 カレントディレクトリに存在するLookPathTest.exeを指定しましたが、cannot run executable found relative to current directory(現在のディレクトリに関連して見つかった実行可能ファイルを実行できません)のエラーが発生しました。
関数の説明に下記記載がありましたので、errors.Is関数を使って試してみます。

古いバージョンの Go では、LookPath は現在のディレクトリからの相対パスを返すことができました。 Go 1.19 以降、LookPath は代わりに、errors.Is(err, ErrDot) を満たすエラーと共にそのパスを返します。詳細については、パッケージのドキュメントを参照してください。

◆テストコード

package main

import (
    "errors"
    "fmt"
    "os"
    "os/exec"
)

func main() {
    if len(os.Args) != 2 {
        fmt.Fprintln(os.Stderr, "usage: LookPathTest.exe fileName")
        os.Exit(1)
    }
    s, e := exec.LookPath(os.Args[1])
    if s != "" {
        fmt.Printf("path=[%s]\n", s)
    }
    if e != nil {
        if errors.Is(e, exec.ErrDot) {
            fmt.Fprintln(os.Stderr, "ErrorDot")
        } else if errors.Is(e, exec.ErrNotFound) {
            fmt.Fprintln(os.Stderr, "ErrNotFound")
        } else if errors.Is(e, exec.ErrWaitDelay) {
            fmt.Fprintln(os.Stderr, "ErrWaitDelay")
        }
        fmt.Fprintf(os.Stderr, "ERROR=[%v]\n", os.NewSyscallError("os.LookPath", e))
    }
}

コードの説明 実行時の引数で指定したファイルの検索結果を出力します。
戻り値のstringに値が存在する場合は、stringをパスとして出力します。
戻り値のerrorに値が存在する場合は、errors.Is関数のエラー判断結果を出力します。

◆実行結果(Windows)

実行結果の説明カレントディレクトリに存在するLookPathTest.exeを指定した結果、ファイル名が表示されてexec.ErrDotが真になりました。
存在するファイルですが、戻り値のerrに値が入ってしまう点は注意ですね。

実行結果の説明存在しないファイルを指定すると戻り値のstringが空でexec.ErrNotFoundが真になりました。

◆実行結果(Linux)

実行結果の説明Linuxでは、実行権(x)が無いファイルを指定するとpermission deniedが発生しました。

実行結果の説明実行権(x)を付与することでファイルを見つけることができました。

最後までご覧いただきありがとうございます