path 實現了對斜杠分隔的路徑的實用操作函數,path/filePath
包實現了兼容各操作系統的文件路徑的實用操作函數。path 包中提供的函數,path/filePath
包都有提供,功能類似,但實現不同。一般應該總是使用path/filePath
包,而不是 path 包,但是本文還是對 path 包的使用進行介紹。
path 包
常用方法
path 實現了對斜杠分隔的路徑的實用操作函數,常用方法如下:
// 判斷路徑是否是一個絕對路徑(按 Linux 中路徑判斷,以 / 開頭為根路徑)
func IsAbs(path string) bool
// 將路徑從最后一個斜杠后面位置分隔為兩個部分(dir 和 file)並返回
// 如果路徑中沒有斜杠,函數返回值 dir 會設為空字符串,file 會設為 path。兩個返回值滿足 path == dir+file
func Split(path string) (dir, file string)
// 將任意數量的路徑元素放入一個單一路徑里,會根據需要添加斜杠。結果是經過簡化的,所有的空字符串元素會被忽略
func Join(elem ...string) string
// 返回路徑除去最后一個路徑元素的部分,即該路徑最后一個元素所在的目錄
// 內部使用 Split 函數去掉最后一個元素后,會簡化路徑並去掉末尾的斜杠
// 如果路徑是空字符串,會返回".";如果路徑由 1 到多個斜杠后跟 0 到多個非斜杠字符組成,會返回"/";其他任何情況下都不會返回以斜杠結尾的路徑
func Dir(path string) string
// 返回路徑的最后一個元素,在提取元素前會求掉末尾的斜杠。如果路徑是"",會返回".";如果路徑是只有一個斜桿構成,會返回"/"
func Base(path string) string
// 返回 path 文件擴展名。返回值是路徑最后一個斜杠分隔出的路徑元素的最后一個'.'起始的后綴(包括'.')。如果該元素沒有'.'會返回空字符串
func Ext(path string) string
// 通過單純的詞法操作返回和 path 代表同一地址的最短路徑
// 它會不斷的依次應用如下的規則,直到不能再進行任何處理:
// 1. 將連續的多個斜杠替換為單個斜杠
// 2. 剔除每一個 . 路徑名元素(代表當前目錄)
// 3. 剔除每一個路徑內的 .. 路徑名元素(代表父目錄)和它前面的非 .. 路徑名元素
// 4. 剔除開始一個根路徑的 .. 路徑名元素,即將路徑開始處的"/.."替換為"/"
// 只有路徑代表根地址"/"時才會以斜杠結尾。如果處理的結果是空字符串,Clean 會返回"."
func Clean(path string) string
// 如果 name 匹配 shell 文件名模式匹配字符串,Match 函數返回真。該模式匹配字符串語法為:
// pattern:
// { term }
// term:
// '*' 匹配 0 或多個非 / 的字符
// '?' 匹配 1 個非 / 的字符
// '[' [ '^' ] { character-range } ']' 字符組(必須非空)
// c 匹配字符 c(c != '*', '?', '\\', '[')
// '\\' c 匹配字符 c
// character-range:
// c 匹配字符 c(c != '\\', '-', ']')
// '\\' c 匹配字符 c
// lo '-' hi 匹配區間 [lo, hi] 內的字符
// Match 要求匹配整個 name 字符串,而不是它的一部分。只有 pattern 語法錯誤時,會返回 ErrBadPattern
func Match(pattern, name string) (matched bool, err error)
基本使用
package main
import (
"fmt"
"path"
)
func main() {
fmt.Println(path.IsAbs("C:/aa/bb/test.txt")) // false,以 Linux 文件路徑判斷
fmt.Println(path.Split("C:/aa/bb/test.txt")) // C:/aa/bb/ test.txt
fmt.Println(path.Join("C:", "aa", "bb", "test.txt")) // C:/aa/bb/test.txt
fmt.Println(path.Dir("C:/aa/bb/test.txt")) // C:/aa/bb
fmt.Println(path.Base("C:/aa/bb/test.txt")) // test.txt
fmt.Println(path.Ext("C:/aa/bb/test.txt")) // .txt
fmt.Println(path.Clean("C:/aa/../aa//bb/test.txt")) // C:/aa/bb/test.txt
fmt.Println(path.Match("C:/aa/*/", "C:/aa/bb/")) // true <nil>
}
path/filePath 包
常用方法
path/filePath
包實現了兼容各操作系統的文件路徑的實用操作函數,常用方法如下:
const (
Separator = os.PathSeparator // 路徑分隔符(例如:'/')
ListSeparator = os.PathListSeparator // 環境變量分隔符(例如:':')
)
// 判斷路徑是否是一個絕對路徑
func IsAbs(path string) bool
// 返回 path 代表的絕對路徑,如果 path 不是絕對路徑,會加入當前工作目錄以使之成為絕對路徑
// 因為硬鏈接的存在,不能保證返回的絕對路徑是唯一指向該地址的絕對路徑
func Abs(path string) (string, error)
// 返回 targpath 相對於 basepath 的相對路徑
// 如果兩個參數一個是相對路徑而另一個是絕對路徑,或者 targpath 無法表示為相對於 basepath 的路徑,將返回錯誤
func Rel(basepath, targpath string) (string, error)
// 將 PATH 或 GOPATH 等環境變量里的多個路徑分割開(這些路徑被 OS 特定的表分隔符連接起來)
// 與 strings.Split 函數的不同之處是:對 "",SplitList 返回 []string{},而 strings.Split 返回 []string{""}。
func SplitList(path string) []string
// 將路徑從最后一個斜杠后面位置分隔為兩個部分(dir 和 file)並返回
// 如果路徑中沒有斜杠,函數返回值 dir 會設為空字符串,file 會設為 path。兩個返回值滿足 path == dir+file
func Split(path string) (dir, file string)
// 將任意數量的路徑元素放入一個單一路徑里,會根據需要添加斜杠。結果是經過簡化的,所有的空字符串元素會被忽略
func Join(elem ...string) string
// 將 path 中的斜杠('/')替換為路徑分隔符並返回替換結果,多個斜杠會替換為多個路徑分隔符
func FromSlash(path string) string
// 將 path 中的路徑分隔符替換為斜杠('/')並返回替換結果,多個路徑分隔符會替換為多個斜杠
func ToSlash(path string) string
// 返回最前面的卷名。如 Windows 系統里提供參數"C:\foo\bar" 會返回"C:";
// Unix/linux 系統的"\\host\share\foo" 會返回"\\host\share";其他平台會返回""
func VolumeName(path string) (v string)
// 返回路徑除去最后一個路徑元素的部分,即該路徑最后一個元素所在的目錄
// 在使用 Split 去掉最后一個元素后,會簡化路徑並去掉末尾的斜杠。如果路徑是空字符串,會返回".";
// 如果路徑由 1 到多個路徑分隔符后跟 0 到多個非路徑分隔符字符組成,會返回單個路徑分隔符;其他任何情況下都不會返回以路徑分隔符結尾的路徑
func Dir(path string) string
// 返回路徑的最后一個元素。在提取元素前會求掉末尾的路徑分隔符。如果路徑是"",會返回".";如果路徑是只有一個斜桿構成,會返回單個路徑分隔符
func Base(path string) string
// 返回 path 文件擴展名。返回值是路徑最后一個路徑元素的最后一個'.'起始的后綴(包括'.')。如果該元素沒有'.'會返回空字符串
func Ext(path string) string
// 通過單純的詞法操作返回和 path 代表同一地址的最短路徑
// 它會不斷的依次應用如下的規則,直到不能再進行任何處理:
// 1. 將連續的多個路徑分隔符替換為單個路徑分隔符
// 2. 剔除每一個 . 路徑名元素(代表當前目錄)
// 3. 剔除每一個路徑內的 .. 路徑名元素(代表父目錄)和它前面的非 .. 路徑名元素
// 4. 剔除開始一個根路徑的 .. 路徑名元素,即將路徑開始處的"/.." 替換為"/"(假設路徑分隔符是'/')
// 返回的路徑只有其代表一個根地址時才以路徑分隔符結尾,如 Unix 的"/"或 Windows 的`C:\`
// 如果處理的結果是空字符串,Clean 會返回"."
func Clean(path string) string
// 返回 path 指向的符號鏈接(軟鏈接)所包含的路徑。如果 path 和返回值都是相對路徑,會相對於當前目錄;除非兩個路徑其中一個是絕對路徑
func EvalSymlinks(path string) (string, error)
// 如果 name 匹配 shell 文件名模式匹配字符串,Match 函數返回真。該模式匹配字符串語法為:
// pattern:
// { term }
// term:
// '*' 匹配 0 或多個非路徑分隔符的字符
// '?' 匹配 1 個非路徑分隔符的字符
// '[' [ '^' ] { character-range } ']' 字符組(必須非空)
// c 匹配字符 c(c != '*', '?', '\\', '[')
// '\\' c 匹配字符 c
// character-range:
// c 匹配字符 c(c != '\\', '-', ']')
// '\\' c 匹配字符 c
// lo '-' hi 匹配區間 [lo, hi] 內的字符
// Match 要求匹配整個 name 字符串,而不是它的一部分。只有 pattern 語法錯誤時,會返回 ErrBadPattern
// Windows 系統中,不能進行轉義:'\\'被視為路徑分隔符
func Match(pattern, name string) (matched bool, err error)
// 返回所有匹配模式匹配字符串 pattern 的文件或者 nil(如果沒有匹配的文件)
// pattern 的語法和 Match 函數相同。pattern 可以描述多層的名字,如 /usr/*/bin/ed(假設路徑分隔符是'/')
func Glob(pattern string) (matches []string, err error)
// Walk 函數對每一個文件/目錄都會調用 WalkFunc 函數類型值。調用時 path 參數會包含 Walk 的 root 參數
// 作為前綴;就是說,如果 Walk 函數的 root 為"dir",該目錄下有文件"a",將會使用"dir/a"調用 walkFn 參
// 數。walkFn 參數被調用時的 info 參數是 path 指定的地址(文件/目錄)的文件信息,類型為 os.FileInfo。
// 如果遍歷 path 指定的文件或目錄時出現了問題,傳入的參數 err 會描述該問題,WalkFunc 類型函數可以決定如
// 何去處理該錯誤(Walk 函數將不會深入該目錄);如果該函數返回一個錯誤,Walk 函數的執行會中止;只有一個例
// 外,如果 Walk 的 walkFn 返回值是 SkipDir,將會跳過該目錄的內容而 Walk 函數照常執行處理下一個文件。
type WalkFunc func(path string, info os.FileInfo, err error) error
// 遍歷 root 指定的目錄下的文件樹,對每一個該文件樹中的目錄和文件都會調用 walkFn,包括 root 自身。
// 所有訪問文件 / 目錄時遇到的錯誤都會傳遞給 walkFn 過濾。文件是按詞法順序遍歷的,這讓輸出更漂亮,
// 但也導致處理非常大的目錄時效率會降低。Walk函數不會遍歷文件樹中的符號鏈接(快捷方式)文件包含的路徑。
func Walk(root string, walkFn WalkFunc) error
基本使用
package main
import (
"fmt"
"os"
"path/filepath"
)
func main() {
// filepath 包的函數會兼容各操作系統,所以相同函數在各個操作系統下返回可能不同
fmt.Println(string(filepath.Separator)) // \
fmt.Println(string(filepath.ListSeparator)) // ;
fmt.Println(filepath.IsAbs("C:/aa/bb/test.txt")) // true
fmt.Println(filepath.Abs("./main.go")) // F:\Go\src\testProject\main.go <nil>
fmt.Println(filepath.Rel("C:/aa", "C:/aa/bb/test.txt")) // bb\test.txt <nil>
fmt.Println(filepath.SplitList("C:/go/bin;D:/Java/jdk;E:/bin")) // [C:/go/bin D:/Java/jdk E:/bin]
fmt.Println(filepath.Split("C:/aa/bb/test.txt")) // C:/aa/bb/ test.txt
fmt.Println(filepath.Join("C:", "\\aa", "/bb", "\\test.txt")) // C:\aa\bb\test.txt
// 將路徑中的 \\ 更換為 /
fmt.Println(filepath.FromSlash("C:\\aa//bb//cc\\test.txt")) // C:\aa\\bb\\cc\test.txt
// 將路徑中的 / 替換為 \\
fmt.Println(filepath.ToSlash("C:\\aa//bb//cc\\test.txt")) // C:/aa//bb//cc/test.txt
fmt.Println(filepath.VolumeName("C:/aa/bb/test.txt")) // C:
fmt.Println(filepath.Dir("C:/aa/bb/test.txt")) // C:\aa\bb
fmt.Println(filepath.Base("C:/aa/bb/test.txt")) // test.txt
fmt.Println(filepath.Ext("C:/aa/bb/test.txt")) // .txt
fmt.Println(filepath.Clean("C:/aa/../aa//bb/test.txt")) // C:/aa/bb/test.txt
fmt.Println(filepath.Match("C:/aa/*/", "C:/aa/bb/")) // true <nil>
// 獲取 C:/aa/bb 目錄下所有 .txt 文件
fmt.Println(filepath.Glob("C:/aa/bb/*.txt")) // [C:\aa\bb\test.txt C:\aa\bb\test1.txt C:\aa\bb\test2.txt] <nil>
// 遍歷 C:/aa/bb 目錄下所有文件
filepath.Walk("C:/aa/bb", func(path string, info os.FileInfo, err error) error {
fmt.Println("Path:", path, "IsDir:", info.IsDir(), "size:", info.Size())
return nil
})
// 變量結果:
// Path: C:/aa/bb IsDir: true size: 0
// Path: C:\aa\bb\test.txt IsDir: false size: 5
// Path: C:\aa\bb\test1.txt IsDir: false size: 6
// Path: C:\aa\bb\test2.txt IsDir: false size: 69
}