首页 > 编程笔记 > Go语言笔记 阅读:15

Go语言path包:获取路径信息(附带实例)

Go 语言的内置包 os 可以执行目录或文件的创建、删除、修改操作,但无法对目录或文件执行更复杂的操作,例如获取目录下的所有文件、获取路径匹配规则、获取文件扩展名、判断绝对路径等。如果需要实现上述功能,则可以使用内置包 path 和 path/filepath 实现。

在内置包 path 的源码文件中,所有功能编写在源码文件 match.go 和 path.go 中,其余带有 _test.go 的源码文件是功能测试代码,如下图所示,主要实现目录路径的截取、清洗、拼接和正则匹配等功能。


图 1 内置包path的源码文件

内置包 path 定义 8 个功能函数,每个函数的功能以及使用说明如下:
package main

import (
   "fmt"
   "path"
)

func main() {
   // 判断路径是不是绝对路径
   fmt.Printf("IsAbs函数:%v\n", path.IsAbs("./a/b"))
   // path.IsAbs仅兼容Linux,不兼容Windows,因此输出false
   fmt.Printf("IsAbs函数:%v\n", path.IsAbs("D:a/b"))
   // 路径拼接,连接后自动调用Clean函数
   fmt.Printf("Join函数:%v\n", path.Join("./a", "b/c", "../d/"))
   // 返回路径的最后一个元素
   fmt.Printf("Base函数:%v\n", path.Base("D:/a/b/c"))
   // 如果路径为空字符串或斜杠,返回实心点或斜杠
   fmt.Printf("Base函数:%v\n", path.Base(""))
   fmt.Printf("Base函数:%v\n", path.Base("/"))
   // 返回等价的最短路径
   // 1.用一个斜线替换多个斜线
   // 2.清除当前路径的实心点
   // 3.清除..和它前面的元素
   // 4.以/..开头的,变成/
   fmt.Printf("Clean函数:%v\n", path.Clean("./a/b/c/../"))
   // 返回路径最后一个元素前面的目录
   // 若路径为空,则返回实心点
   fmt.Printf("Dir函数:%v\n", path.Dir("D:/a/b/c"))
   // 返回路径中的文件扩展名
   // 若没有文件扩展名,则返回空
   fmt.Printf("Ext函数:%v\n", path.Ext("D:/a/b/c/d.jpg"))
   // 匹配路径,若完全匹配,则返回true
   // *匹配0个或多个非/的字符
   matched1, _ := path.Match("*", "abc")
   fmt.Printf("Match函数:%v\n", matched1)
   // ?匹配一个非/的字符,a?b的?是匹配ab之间的字符,但无法匹配斜杠“/”
   matched2, _ := path.Match("a?b", "agb")
   fmt.Printf("Match函数:%v\n", matched2)
   // 匹配路径是否符合a/*/c格式,如a/abc/c和a/bbb/都能匹配
   matched3, _ := path.Match("a/*/c", "a/bb/c")
   fmt.Printf("Match函数:%v\n", matched3)
   // 分割路径中的目录与文件
   dir, file := path.Split("./a/b/c/d.jpg")
   fmt.Printf("Split函数:目录:%v、文件:%v\n", dir, file)
}
运行上述代码,结果为:

IsAbs函数:false
IsAbs函数:false
Join函数:a/b/d
Base函数:c
Base函数:.
Base函数:/
Clean函数:a/b
Dir函数:D:/a/b
Ext函数:.jpg
Match函数:true
Match函数:true
Match函数:true
Split函数:目录:./a/b/c/、文件:d.jpg


分析上述例子,我们对内置包 path 的 8 个函数进行归纳总结,说明如下:

函数 功能
IsAbs(path string) bool 判断参数 path 是否为绝对路径,若为绝对路径,则返回 true,否则返回 false,但仅兼容 Linux,不兼容 Windows。
Join(elem...string) string 从可选参数 elem 中获取多个路径拼接的新路径,如果没有设置参数 elem,则返回空字符串。
Base(path string) string 获取路径最后一个元素,如 D:/a/b/c 则获取文件夹 c,D:/a/b/c.jpg 则获取文件 c.jpg。如果路径是空字符串,则返回实心点“.”;如果路径只有一个或多个斜杠(“//”或“\\”),则返回路径分隔符(即斜杠“/”或“\”)。
Clean(path string) string 返回路径的最短路径,简单来说是对路径进行清洗处理,一共设置了 4 种清洗规则。
Dir(path string) string 获取路径最后一个元素前面的路径,如参数 path 设置 D:/a/b/c,则返回 D:/a/b,去掉 c 文件夹。
Ext(path string) string 获取文件扩展名,参数 path 是文件路径信息,如果参数 path 不是文件路径,则返回空字符串,如参数 path 设为 D:/a/b/c 则返回空字符串。
Match(pattern, name string) (matched bool, err error) 通过正则表达式匹配路径信息。参数 pattern 是正则表达式的匹配符,参数 name 是需要被匹配的路径,返回值 matched 是匹配结果,返回值 err 是匹配错误信息。
Split(path string) (dir, file string) 分割路径中的目录与文件,参数 path 是需要被分割的路径,返回值 dir 是分割后的路径,返回值 file 是分割后的文件。如果参数 path 不是文件路径,则返回值 dir 为路径最后一个元素前面的路径,返回值 file 为空字符串,例如 ./a/b/c/d,返回值 dir 为 ./a/b/c/。

内置包 path/filepath 所有功能编写在源码文件 match.go、path.go、symlink.go,path_unix.go、path_plan9.go、path_windows.go、symlink_windows.go 和 symlink_unix.go 中,其余带有 _test.go 的源码文件是功能测试代码,如下图所示,它含有内置包 path 的功能,并且能兼容所有操作系统。


图 2 path/filepath的源码文件

内置包 path/filepath 定义 16 个功能函数,每个函数的功能以及使用说明如下:
package main

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

func main() {
    // 判断路径是不是绝对路径,filepath兼容所有操作系统
    fmt.Printf("IsAbs函数:%v\n", filepath.IsAbs("./a/b/c"))
    fmt.Printf("IsAbs函数:%v\n", filepath.IsAbs("C:/a/b/c"))
    // 返回所给路径的绝对路径
    path, _ := filepath.Abs("go.mod")
    fmt.Printf("Abs函数:%v\n", path)
    // 返回路径最后一个元素
    fmt.Printf("Base函数:%v\n", filepath.Base("D:/a/c/1.txt"))
    // 如果路径为空字符串,则返回实心点
    fmt.Printf("Base函数:%v\n", filepath.Base(""))
    // 如果路径有一个或多个斜杠/,则返回单个斜杠/
    fmt.Printf("Base函数:%v\n", filepath.Base("//"))
    // 返回等价的最短路径
    // 1.用一个斜线替换多个斜线
    // 2.清除当前路径的实心点
    // 3.清除..和它前面的元素
    // 4.以/..开头的,变成/
    fmt.Printf("Clean函数:%v\n", filepath.Clean("D:/a/b/../c"))
    fmt.Printf("Clean函数:%v\n", filepath.Clean("D:/a/b/../c/1.txt"))
    // 返回路径最后一个元素前面的目录
    // 若路径为空,则返回实心点
    fmt.Printf("Dir函数:%v\n", filepath.Dir("./a/b/c"))
    fmt.Printf("Dir函数:%v\n", filepath.Dir("D:/a/b/c"))
    // 返回软链接的实际路径
    path2, _ := filepath.EvalSymlinks("go.mod")
    fmt.Printf("EvalSymlinks函数:%v\n", path2)
    // 返回文件路径的扩展名
    // 如果不是文件路径,则返回空字符串
    fmt.Printf("Ext函数:%v\n", filepath.Ext("./a/b/c/d.jpg"))
    // 将路径中的/替换为路径分隔符
    fmt.Printf("FromSlash函数:%v\n", filepath.FromSlash("./a/b/c"))
    // 返回路径中所有匹配的文件
    match, _ := filepath.Glob("./*.go")
    fmt.Printf("Glob函数:%v\n", match)
    // 路径拼接,连接后自动调用Clean函数
    fmt.Printf("Join函数:%v\n", filepath.Join("C:/a", "/b", "/c"))
    // *匹配0个或多个非/的字符
    matched1, _ := filepath.Match("*", "abc")
    fmt.Printf("Match函数:%v\n", matched1)
    // ?匹配一个非/的字符,a?b的?是指a和b之间只要不是斜杠“/”,并且a和b之间只有一个字符都能
匹配
    matched2, _ := filepath.Match("a?b", "agb")
    fmt.Printf("Match函数:%v\n", matched2)
    // 匹配路径是否符合a/*/c格式,如a/abc/c和a/bbb/都能匹配
    matched3, _ := filepath.Match("a/*/c", "a/bb/c")
    fmt.Printf("Match函数:%v\n", matched3)
    // 返回以参数basepath为基准的相对路径
    path3, _ := filepath.Rel("C:/a/b", "C:/a/b/../e")
    fmt.Printf("Rel函数:%v\n", path3)
    // 将路径使用路径列表分隔符分开,见os.PathListSeparator
    // Linux默认为冒号,Windows默认为分号
    sl := filepath.SplitList("C:/windows;C:/windows/system")
    fmt.Printf("SplitList函数:%v,长度:%v\n", sl, len(sl))
    // 分割路径中的目录与文件
    dir, file := filepath.Split("C:/a/d.jpg")
    fmt.Printf("Split函数:目录:%v,文件:%v\n", dir, file)
    // 将路径分隔符使用/替换
    fmt.Printf("ToSlash函数:%v\n", filepath.ToSlash("C:\\a\\b"))
    // 返回分区名
    vn := filepath.VolumeName("C:/a/b/c")
    fmt.Printf("VolumeName函数:%v\n", vn)
    // 遍历指定目录下的所有文件
    filepath.Walk("./",func(path string,info os.FileInfo,err error)error{
         fmt.Printf("Walk函数:%v\n", path)
         return nil
    })
}
运行上述代码,运行结果为:
IsAbs函数:false
IsAbs函数:true
Abs函数:E:\mygo\go.mod
Base函数:1.txt
Base函数:.
Base函数:\
Clean函数:D:\a\c
Clean函数:D:\a\c\1.txt
Dir函数:a/b
Dir函数:D:\a\b
EvalSymlinks函数:go.mod
Ext函数:.jpg
FromSlash函数:.\a\b\c
Glob函数:[chapter14.2.2.go]
Join函数:C:\a\b\c
Match函数:true
Match函数:true
Match函数:true
Rel函数:..\e
SplitList函数:[C:\windows C:\windows\system],长度:2
Split函数:目录:C:/a/,文件:d.jpg
ToSlash函数:C:/a/b
VolumeName函数:C:
Walk函数:./
Walk函数:.idea

分析上述例子,我们对内置包 path/filepath 的 16 个函数进行归纳总结,说明如下:

函数 功能
IsAbs(path string) (b bool) 判断参数 path 是否为绝对路径。
Abs(path string) (string, error) 根据参数 path 返回绝对路径。
Base(path string) string 与内置包 path 的 Base() 函数的功能相同。
Clean(path string) string 与内置包 path 的 Clean() 函数的功能相同。
Dir(path string) string 与内置包 path 的 Dir() 函数的功能相同。
EvalSymlinks(path string) (string, error) 返回软链接文件的路径信息。软链接文件是 Linux 文件的一种,类似于 Windows 的快捷方式。
Ext(path string) string 与内置包 path 的 Ext() 函数的功能相同。
Glob(pattern string) (matches []string, err error) 通过正则表达式匹配路径中符合条件的文件,参数 pattern 是带有正则表达式的路径信息。
Join(elem ...string) string 与内置包 path 的 Join() 函数的功能相同。
Match(pattern, name string) (matched bool, err error) 与内置包 path 的 Match() 函数的功能相同。
SplitList(path string) []string 对多个路径信息进行分割,以切片方式返回结果,Linux 默认以冒号分割,Windows 默认以分号分割。
Split(path string) (dir, file string) 与内置包 path 的 Split() 函数的功能相同。
ToSlash(path string) string 将参数 path 的路径分隔符(即“\”)替换为斜杠“/”并返回替换结果。
FromSlash(path string) string 将参数 path 的斜杠“/”替换为路径分隔符(即“\”)并返回替换结果。
VolumeName(path string) string 返回最前面的卷名,Windows 系统返回盘符(即 C 盘、D 盘等),Linux 系统返回上一级目录(如 \host\share\foo 返回 \host\share)。
Walk(root string, fn WalkFunc) error 遍历参数 root 的所有文件名,在开发中十分常用。

相关文章