------------------------------------------------------------ filepath 中的函數會根據不一樣平臺作不一樣的處理,好比路徑分隔符、卷名等。 ------------------------------------------------------------ 路徑分隔符轉換: const ( Separator = os.PathSeparator // 路徑分隔符(分隔路徑元素) ListSeparator = os.PathListSeparator // 路徑列表分隔符(分隔多個路徑) ) 下面兩個函數主要用於將 Windows 路徑分隔符轉換爲 Linux 路徑分隔符,處理完後再轉換回去,只在 Windows 中有用,在 Linux 中不必: // 將 path 中平臺相關的路徑分隔符轉換爲 '/' ToSlash(path string) string // 將 path 中的 '/' 轉換爲系統相關的路徑分隔符 FromSlash(path string) string func main() { s := `http://www.site.com/a/b/c/d` u, _ := url.Parse(s) s = u.Path // 下面這句用於 Windows 系統 s = filepath.FromSlash(s) fmt.Println(s) // /a/b/c/d 或 \a\b\c\d // 建立目錄試試 if err := os.MkdirAll(s[1:], 0777); err != nil { fmt.Println(err) } // 下面這句用於 Windows 系統 s = filepath.ToSlash(s) fmt.Println(s) // /a/b/c/d } ------------------------------------------------------------ // 獲取 path 中最後一個分隔符以前的部分(不包含分隔符) Dir(path string) string // 獲取 path 中最後一個分隔符以後的部分(不包含分隔符) Base(path string) string // 獲取 path 中最後一個分隔符先後的兩部分 // 以前包含分隔符,以後不包含分隔符 Split(path string) (dir, file string) // 獲取路徑字符串中的文件擴展名 Ext(path string) string func main() { path := `a///b///c///d` path = filepath.FromSlash(path) // 平臺處理 d1 := filepath.Dir(path) f1 := filepath.Base(path) d2, f2 := filepath.Split(path) fmt.Printf("%q %q\n%q %q\n", d1, f1, d2, f2) // "a/b/c" "d" // "a///b///c///" "d" ext := filepath.Ext(path) fmt.Println(ext) // .txt } ------------------------------------------------------------ // 獲取 targpath 相對於 basepath 的路徑。 // 要求 targpath 和 basepath 必須「都是相對路徑」或「都是絕對路徑」。 Rel(basepath, targpath string) (string, error) func main() { // 都是絕對路徑 s, err := filepath.Rel(`/a/b/c`, `/a/b/c/d/e`) fmt.Println(s, err) // d/e <nil> // 都是相對路徑 s, err = filepath.Rel(`a/b/c`, `a/b/c/d/e`) fmt.Println(s, err) // d/e <nil> // 一個絕對一個相對 s, err = filepath.Rel(`/a/b/c`, `a/b/c/d/e`) fmt.Println(s, err) // Rel: can't make a/b/c/d/e relative to /a/b/c // 一個相對一個絕對 s, err = filepath.Rel(`a/b/c`, `/a/b/c/d/e`) fmt.Println(s, err) // Rel: can't make /a/b/c/d/e relative to a/b/c // 從 `a/b/c` 進入 `a/b/d/e`,只須要進入 `../d/e` 便可 s, err = filepath.Rel(`a/b/c`, `a/b/d/e`) fmt.Println(s, err) // ../d/e <nil> } ------------------------------------------------------------ // 將 elem 中的多個元素合併爲一個路徑,忽略空元素,清理多餘字符。 Join(elem ...string) string func main() { // Linux 示例 s := filepath.Join("a", "b", "", ":::", " ", `//c////d///`) fmt.Println(s) // a/b/:::/ /c/d } ------------------------------------------------------------ // 清理路徑中的多餘字符,好比 /// 或 ../ 或 ./ Clean(path string) string func main() { // Linux 示例 s := filepath.Clean("a/./b/:::/..// /c/..///d///") fmt.Println(s) // a/b/ /d } ------------------------------------------------------------ // 獲取 path 的絕對路徑 Abs(path string) (string, error) // 判斷路徑是否爲絕對路徑 IsAbs(path string) bool func main() { s1 := `a/b/c/d` fmt.Println(filepath.Abs(s1)) // 不一樣系統顯示不同 s2 := `/a/b/c/d` fmt.Println(filepath.IsAbs(s1)) // false fmt.Println(filepath.IsAbs(s2)) // true } ------------------------------------------------------------ // 將路徑序列 path 分割爲多條獨立的路徑 SplitList(path string) []string func main() { path := `a/b/c:d/e/f: g/h/i` s := filepath.SplitList(path) fmt.Printf("%q", s) // ["a/b/c" "d/e/f" " g/h/i"] } ------------------------------------------------------------ // 返回路徑字符串中的卷名 // Windows 中的 `C:\Windows` 會返回 "C:" // Linux 中的 `//host/share/name` 會返回 `//host/share` VolumeName(path string) string // 返回連接(快捷方式)所指向的實際文件 EvalSymlinks(path string) (string, error) ------------------------------------------------------------ // 判斷 name 是否和指定的模式 pattern 徹底匹配 Match(pattern, name string) (matched bool, err error) // pattern 規則以下: // 可使用 ? 匹配單個任意字符(不匹配路徑分隔符)。 // 可使用 * 匹配 0 個或多個任意字符(不匹配路徑分隔符)。 // 可使用 [] 匹配範圍內的任意一個字符(能夠包含路徑分隔符)。 // 可使用 [^] 匹配範圍外的任意一個字符(無需包含路徑分隔符)。 // [] 以內可使用 - 表示一個區間,好比 [a-z] 表示 a-z 之間的任意一個字符。 // 反斜線用來匹配實際的字符,好比 \* 匹配 *,\[ 匹配 [,\a 匹配 a 等等。 // [] 以內能夠直接使用 [ * ?,但不能直接使用 ] -,須要用 \]、\- 進行轉義。 func main() { fmt.Println(filepath.Match(`???`, `abc`)) // true fmt.Println(filepath.Match(`???`, `abcd`)) // false fmt.Println(filepath.Match(`*`, `abc`)) // true fmt.Println(filepath.Match(`*`, ``)) // true fmt.Println(filepath.Match(`a*`, `abc`)) // true fmt.Println(filepath.Match(`???\\???`, `abc\def`)) // true fmt.Println(filepath.Match(`???/???`, `abc/def`)) // true fmt.Println(filepath.Match(`/*/*/*/`, `/a/b/c/`)) // true fmt.Println(filepath.Match(`[aA][bB][cC]`, `aBc`)) // true fmt.Println(filepath.Match(`[^aA]*`, `abc`)) // false fmt.Println(filepath.Match(`[a-z]*`, `a+b`)) // true fmt.Println(filepath.Match(`\[*\]`, `[a+b]`)) // true fmt.Println(filepath.Match(`[[\]]*[[\]]`, `[]`)) // true } ------------------------------------------------------------ // 列出與指定的模式 pattern 徹底匹配的文件或目錄(匹配原則同上) Glob(pattern string) (matches []string, err error) func main() { // 列出 usr 的子目錄中所包含的以 ba(忽略大小寫)開頭的項目 list, err := filepath.Glob("/usr/*/[Bb][Aa]*") if err != nil { fmt.Println(err) } for _, v := range list { fmt.Println(v) } } ------------------------------------------------------------ // 遍歷指定目錄(包括子目錄),對遍歷到的項目用 walkFn 函數進行處理。 Walk(root string, walkFn WalkFunc) error // 文件處理函數定義以下,若是 WalkFunc 返回 nil,則 Walk 函數繼續 // 遍歷,若是返回 SkipDir,則 Walk 函數會跳過當前目錄(若是當前遍 // 歷到的是文件,則同時跳事後續文件及子目錄),繼續遍歷下一個目錄。 // 若是返回其它錯誤,則 Walk 函數會停止遍歷過程。 // 在 Walk 遍歷過程當中,若是遇到錯誤,則會將錯誤經過 err 傳遞給 // WalkFunc 函數,同時 Walk 會跳過出錯的項目,繼續處理後續項目。 type WalkFunc func(path string, info os.FileInfo, err error) error // WalkFunc 函數: // 列出含有 *.txt 文件的目錄(不是所有,由於會跳過一些子目錄) func findTxtDir(path string, info os.FileInfo, err error) error { ok, err := filepath.Match(`*.txt`, info.Name()) if ok { fmt.Println(filepath.Dir(path), info.Name()) // 遇到 txt 文件則繼續處理所在目錄的下一個目錄 // 注意會跳過子目錄 return filepath.SkipDir } return err } // WalkFunc 函數: // 列出全部以 ab 開頭的目錄(所有,由於沒有跳過任何項目) func findabDir(path string, info os.FileInfo, err error) error { if info.IsDir() { ok, err := filepath.Match(`[aA][bB]*`, info.Name()) if err != nil { return err } if ok { fmt.Println(path) } } return nil } func main() { // 列出含有 *.txt 文件的目錄(不是所有,由於會跳過一些子目錄) err := filepath.Walk(`/usr`, findTxtDir) fmt.Println(err) fmt.Println("==============================") // 列出全部以 ab 開頭的目錄(所有,由於沒有跳過任何項目) err = filepath.Walk(`/usr`, findabDir) fmt.Println(err) } ------------------------------------------------------------ 在 path 包中有一些同名的函數,但它們只處理 Linux 路徑分隔符 '/'。