takuroooのブログ

勉強したこととか

Go path/filepathでファイルパスを操作する

パス名の操作に便利なfilepathを触って見たのでまとめていく。

golang.org

目次

filepath.Abs

相対パス絶対パスに変換

fmt.Println(filepath.Abs("./main.go")) # /hoge/fuga/main.go <nil>

filepath.Base

パスの最後の要素を返す。パス名からファイル名を取得したいときに使える。

fmt.Println(filepath.Base("/dir1/dir2/temp.txt")) // temp.txt
fmt.Println(filepath.Base("/dir1/dir2/"))         // dir2
fmt.Println(filepath.Base("temp.txt"))            // temp.txt
fmt.Println(filepath.Base("./"))                  // .
fmt.Println(filepath.Base("/"))                   // /
fmt.Println(filepath.Base(""))                    // .
  • 与えたパスがスラッシュだけの場合はシングルスラッシュ/を返す。
  • パスが空の場合は.を返す。

filepath.Clean

決まったルールにしたがってパスを整形する。

fmt.Println(filepath.Clean("./dir1/temp.txt"))          // dir1/temp.txt
fmt.Println(filepath.Clean("..//dir1//dir2//temp.txt")) // ../dir1/dir2/temp.txt
fmt.Println(filepath.Clean("dir1/dir2/../temp.txt"))    // dir1/temp.txt
fmt.Println(filepath.Clean("/../dir1"))                 // /dir1

決まったルール

  • ///に変更
  • .を削除
  • パスの途中に..がある場合はその前にある要素と一緒に削除(3番目の例)
  • /../に変更

filepath.Dir

パス名の最後の要素を除いたものを返す。パス名からディレクトリ名を取得したいときに使える。

fmt.Println(filepath.Dir("/dir1/dir2/temp.txt")) // /dir1
fmt.Println(filepath.Dir("/dir1/dir2/"))         // /dir1/dir2
fmt.Println(filepath.Dir("/dir1/dir2"))          // /dir1/dir2
  • 内部ではfilepath.Cleanで処理されたパスが返ってくる。
  • パスがからの場合とスラッシュだけの場合の挙動はfilepath.Baseと一緒

filepath.EvalSymlinks

linkを指定した場合、リンク先のパスを返す。

fmt.Println(filepath.EvalSymlinks("/root/temp")) // /root/hoge/fuga/temp <nil>

filepath.Ext

パス名から拡張子を取得する。

fmt.Println(filepath.Ext("/dir1/temp.txt"))  // .txt
fmt.Println(filepath.Ext("/temp.hoge.fuga")) // .fuga
fmt.Println(filepath.Ext("/dir1"))           // ""

filepath.Glob

指定したpatternに一致するパス名をスライスで返す。

var matches []string
var err error
var pattern string = "./*.txt"
matches, err = filepath.Glob(pattern)
fmt.Println(matches, err)
  • 例では現在のディレクトリにある.txt拡張子を持つファイル一覧を取得する。

filepath.Join

パス名を連結する。

fmt.Println(filepath.Join("abc/", "def"))       // abc/def
fmt.Println(filepath.Join("abc/", "/def"))      // abc/def
fmt.Println(filepath.Join("abc", "def", "hij")) // abc/def/hij

filepath.Match

指定したパス名とパターンが一致するか判定する。

fmt.Println(filepath.Match("/dir1/*", "/dir1/temp.txt"))         // true <nil>
fmt.Println(filepath.Match("/dir1/*/*", "/dir1/dir2/temp.txt"))  // true <nil>
fmt.Println(filepath.Match("/dir1/?bc.txt", "/dir1/abc.txt"))    // true <nil>
fmt.Println(filepath.Match("/dir1/\\[", "/dir1/["))              // true <nil>

パターンに設定できるシンタックス

  • アスタリスク*はセパレータ以外のシーケンスを意味する。
  • ハテナ?はセパレータ以外の1文字を意味する。
  • linuxでは\\エスケープ文字として使われるが、windowsではセパレータとして認識される。

filepath.Rel

2つのパス名を入力すると相対パスを作ってくれる。

fmt.Println(filepath.Rel("/dir1/temp.txt", "/dir1/temp.txt")) // . <nil>
fmt.Println(filepath.Rel("/dir1/", "/dir1/temp.txt"))         // temp.txt <nil>
fmt.Println(filepath.Rel("/dir1/", "/dir1/dir2/temp.txt"))    // dir2/temp.txt <nil>
fmt.Println(filepath.Rel("/hoge/", "/dir1/temp.txt"))         // ../dir1/temp.txt <nil>

filepath.Split

パスをディレクトリ名とファイル名に分割する。

fmt.Println(filepath.Split("/dir1/temp.txt"))      // /dir1/ temp.txt
fmt.Println(filepath.Split("/dir1/dir2/temp.txt")) // /dir1/dir2/ temp.txt
fmt.Println(filepath.Split("/dir1"))               // / dir1
fmt.Println(filepath.Split("/dir1/"))              // /dir1/

filepath.SplitList

os.PathListSeparatorで指定されている文字で分割する。

fmt.Println(filepath.SplitList("/dir1/dir2/:hoge")) // [/dir1/dir2/ hoge]
fmt.Println(string(os.PathListSeparator))           // :

filepath.ToSlash

os.PathSeparatorで指定されている文字を/に変換する。

fmt.Println(filepath.ToSlash("dir1/temp.txt")) // dir1/temp.txt
fmt.Println(string(os.PathSeparator))          // /
  • unix系のosの場合はos.PathSeparator/なので何もしない。

filepath.FromSlash

/os.PathSeparatorで指定されている文字に変換する。

fmt.Println(filepath.FromSlash("dir1/temp.txt")) // dir1/temp.txt
fmt.Println(string(os.PathSeparator))          // /
  • unix系のosの場合はos.PathSeparator/なので何もしない。

filepath.VolumeName

windowsでよくあるドライブ名を取得する。

fmt.Println(filepath.VolumeName("dir1/temp.txt")) // ""
  • unix系のosの場合はなにも返ってこない。

filepath.Walk

指定したパス以下のディレクトリを再帰的に探索していく。

err := filepath.Walk("./",
    func(path string, info os.FileInfo, err error) error {
        if filepath.Ext(path) == ".json" {
            fmt.Println(path)
        }
        return nil
    })
  • 第二引数にWalkFuncを指定するとファイルやディレクトリが見つかるたびにWalkFuncが実行される。
  • WalkFuncの定義は下記のような形式になっている。
type WalkFunc func(path string, info os.FileInfo, err error) error