Go 語言標準庫之 path & path/filepath 包
阿新 • • 發佈:2021-12-06
path 實現了對斜槓分隔的路徑的實用操作函式,path/filePath
包實現了相容各作業系統的檔案路徑的實用操作函式。本文對 path 包和path/filePath
的常用操作進行介紹。
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> }
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
}