Open8

Go + Git Bash の環境変数のファイルパスの扱いの面白い挙動

Shunsuke SuzukiShunsuke Suzuki

windows, Git Bash 上で AQUA_GLOBAL_CONFIG (; 区切りでファイルのパスが指定される)の扱いが妙なので調べたら、 複数のファイルパスを指定した場合 Unix 形式のパスが変換されてないことに気づいた。
というか os.Getenv で Unix 形式のパスが変換されているのが興味深い。

$ export AQUA_GLOBAL_CONFIG='/d/Users/shunsukesuzuki/workspace/aqua-registry/aqua-all.yaml'

$ go run main.go
D:/Users/shunsukesuzuki/workspace/aqua-registry/aqua-all.yaml
;

$ export AQUA_GLOBAL_CONFIG='foo;/d/Users/shunsukesuzuki/workspace/aqua-registry/aqua-all.yaml'

$ go run main.go
foo;/d/Users/shunsukesuzuki/workspace/aqua-registry/aqua-all.yaml
;
package main

import (
	"fmt"
	"os"
)

func main() {
	fmt.Println(os.Getenv("AQUA_GLOBAL_CONFIG"))
	fmt.Println(string(os.PathListSeparator))
}

で、ここで問題なのが Unix 形式のパスだとファイルが見つけられないこと。
os.Getenv の段階で問題になってると辛いな。自分で変換できるのかな。

Shunsuke SuzukiShunsuke Suzuki

windows の形式にすれば問題ないが、 Git Bash であれば Unix 形式も処理できてほしい気もする。

export AQUA_GLOBAL_CONFIG='foo;D:\Users\shunsukesuzuki\workspace\aqua-registry\aqua-all.yaml'
Shunsuke SuzukiShunsuke Suzuki

上の例だと何が問題なのかわかりにくい気がしたので修正。
D:\Users\shunsukesuzuki\workspace\aqua-registry\aqua-all.yaml は読めているが /d/Users/shunsukesuzuki/workspace/aqua-registry/aqua-all.yaml は読めていない。
環境変数が /d/Users/shunsukesuzuki/workspace/aqua-registry/aqua-all.yaml の場合 os.Getenv の段階で D:\Users\shunsukesuzuki\workspace\aqua-registry\aqua-all.yaml に変換されているが、 foo;/d/Users/shunsukesuzuki/workspace/aqua-registry/aqua-all.yaml を filepath.SplitList で分割しても変換されないので、ファイルが読めない。

package main

import (
	"fmt"
	"os"
	"path/filepath"
)

func main() {
	fmt.Println(string(os.PathListSeparator))
	fmt.Println(os.Getenv("AQUA_GLOBAL_CONFIG"))
	for _, p := range filepath.SplitList(os.Getenv("AQUA_GLOBAL_CONFIG")) {
		if _, err := os.Stat(p); err != nil {
			fmt.Println("file doesn't exit:", p)
		} else {
			fmt.Println("file exits:", p)
		}
	}
}
$ echo $AQUA_GLOBAL_CONFIG
foo;D:\Users\shunsukesuzuki\workspace\aqua-registry\aqua-all.yaml

$ go run main.go
;
foo;D:\Users\shunsukesuzuki\workspace\aqua-registry\aqua-all.yaml
file doesn't exit: foo
file exits: D:\Users\shunsukesuzuki\workspace\aqua-registry\aqua-all.yaml

$ export AQUA_GLOBAL_CONFIG='foo;/d/Users/shunsukesuzuki/workspace/aqua-registry/aqua-all.yaml'

$ go run main.go
;
foo;/d/Users/shunsukesuzuki/workspace/aqua-registry/aqua-all.yaml
file doesn't exit: foo
file doesn't exit: /d/Users/shunsukesuzuki/workspace/aqua-registry/aqua-all.yaml

$ export AQUA_GLOBAL_CONFIG='/d/Users/shunsukesuzuki/workspace/aqua-registry/aqua-all.yaml'

$ go run main.go
;
D:/Users/shunsukesuzuki/workspace/aqua-registry/aqua-all.yaml
file exits: D:/Users/shunsukesuzuki/workspace/aqua-registry/aqua-all.yaml
Shunsuke SuzukiShunsuke Suzuki
  • foo:/d/Users/shunsukesuzuki/workspace/aqua-registry/aqua-all.yaml はだめ
  • /d/Users:/d/Users/shunsukesuzuki/workspace/aqua-registry/aqua-all.yaml は OK
  • /d/Users;/d/Users/shunsukesuzuki/workspace/aqua-registry/aqua-all.yaml は だめ

POSIX 形式で絶対パスだと OK

$ export AQUA_GLOBAL_CONFIG='foo:/d/Users/shunsukesuzuki/workspace/aqua-registry/aqua-all.yaml'

$ go run main.go
;
foo:/d/Users/shunsukesuzuki/workspace/aqua-registry/aqua-all.yaml
file doesn't exit: foo:/d/Users/shunsukesuzuki/workspace/aqua-registry/aqua-all.yaml

$ export AQUA_GLOBAL_CONFIG='/d/Users:/d/Users/shunsukesuzuki/workspace/aqua-registry/aqua-all.yaml'

$ go run main.go
;
D:\Users;D:\Users\shunsukesuzuki\workspace\aqua-registry\aqua-all.yaml
file exits: D:\Users
file exits: D:\Users\shunsukesuzuki\workspace\aqua-registry\aqua-all.yaml

$ export AQUA_GLOBAL_CONFIG='/d/Users;/d/Users/shunsukesuzuki/workspace/aqua-registry/aqua-all.yaml'

$ go run main.go
;
/d/Users;/d/Users/shunsukesuzuki/workspace/aqua-registry/aqua-all.yaml
file doesn't exit: /d/Users
file doesn't exit: /d/Users/shunsukesuzuki/workspace/aqua-registry/aqua-all.yaml