参考https://studygolang.com/pkgdoc

标准库path中有的该path/filepath库中都有,所以一般都使用path/filepath

导入方式:

import "path/filepath"

filepath包实现了兼容各操作系统的文件路径的实用操作函数。

1)constants常量

const (
Separator = os.PathSeparator //"/"
ListSeparator = os.PathListSeparator //":"
)

2)var变量

var ErrBadPattern = errors.New("syntax error in pattern")

ErrBadPattern表示一个glob模式匹配字符串的格式错误。

var SkipDir = errors.New("skip this directory")

用作WalkFunc类型的返回值,表示该次调用的path参数指定的目录应被跳过。本错误不应被任何其他函数返回。

3)函数

1》type WalkFunc

type WalkFunc func(path string, info os.FileInfo, err error) 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函数照常执行处理下一个文件。

2》func Walk

func Walk(root string, walkFn WalkFunc) error

Walk函数会遍历root指定的目录下的文件树,对每一个该文件树中的目录和文件都会调用walkFn,包括root自身。所有访问文件/目录时遇到的错误都会传递给walkFn过滤。文件是按词法顺序遍历的,这让输出更漂亮,但也导致处理非常大的目录时效率会降低。Walk函数不会遍历文件树中的符号链接(快捷方式)文件包含的路径。

3》源码

Walk()

func Walk(root string, walkFn WalkFunc) error {
info, err := os.Lstat(root) //获取fileInfo
if err != nil {
err = walkFn(root, nil, err) //如果获取fileInfo的过程中出错了,则将错误err传入walkFn进行处理
} else {
err = walk(root, info, walkFn)//如果成功得到了fileInfo,就将info作为参数,调用walk
}
if err == SkipDir {//如果输出的错误是SkipDir,那么就会跳过该目录的内容
return nil
}
return err
}

walk()

func walk(path string, info os.FileInfo, walkFn WalkFunc) error {
if !info.IsDir() { //如果info传入的是文件,则遍历下一个
return walkFn(path, info, nil)
} names, err := readDirNames(path) //读取path下的所有目录和文件,并返回目录项的排序列表
err1 := walkFn(path, info, err)
// If err != nil, walk can't walk into this directory.
// err1 != nil means walkFn want walk to skip this directory or stop walking.
// Therefore, if one of err and err1 isn't nil, walk will return.
if err != nil || err1 != nil {
// The caller's behavior is controlled by the return value, which is decided
// by walkFn. walkFn may ignore err and return nil.
// If walkFn returns SkipDir, it will be handled by the caller.
// So walk should return whatever walkFn returns.
return err1
}
//遍历文件和目录列表
for _, name := range names {
//连接得到目录或文件路径
filename := Join(path, name)
//然后获取该文件或目录信息
fileInfo, err := lstat(filename)
if err != nil {
if err := walkFn(filename, fileInfo, err); err != nil && err != SkipDir {
return err
}
} else {
//递归
err = walk(filename, fileInfo, walkFn)
if err != nil {
//遍历文件发生错误或者目录发生错误且不能跳过,则返回err
if !fileInfo.IsDir() || err != SkipDir {
return err
}
}
}
}
return nil
}

有了他们,我们就能对指定目录下的目录和文件进行指定的操作walkFunc。

举个最简单的例子,如果想要遍历打印目录root下的文件名,则:

package main
import(
"fmt"
"path/filepath"
"os"
)
func main() {
filepath.Walk("/Users/user/go-learning", func(path string, info os.FileInfo, err error)error{
fmt.Printf("%s \n", path)
return nil
})
}

返回:

userdeMBP:go-learning user$ go run test.go
/Users/user/go-learning
/Users/user/go-learning/.DS_Store
/Users/user/go-learning/hello.go
/Users/user/go-learning/stacker
/Users/user/go-learning/stacker/.DS_Store
/Users/user/go-learning/stacker/stack
/Users/user/go-learning/stacker/stack/stack.go
/Users/user/go-learning/stacker/stacker.go
/Users/user/go-learning/test.go
/Users/user/go-learning/test.txt
/Users/user/go-learning/testCreate.txt

4》func IsAbs

func IsAbs(path string) bool

IsAbs返回路径是否是一个绝对路径。

5》func Abs

func Abs(path string) (string, error)

Abs函数返回path代表的绝对路径,如果path不是绝对路径,会加入当前工作目录以使之成为绝对路径。因为硬链接的存在,不能保证返回的绝对路径是唯一指向该地址的绝对路径。

6》Rel

func Rel(basepath, targpath string) (string, error)

Rel函数返回一个相对路径,将basepath和该路径用路径分隔符连起来的新路径在词法上等价于targpath。也就是说,Join(basepath, Rel(basepath, targpath))等价于targpath本身。如果成功执行,返回值总是相对于basepath的,即使basepath和targpath没有共享的路径元素。如果两个参数一个是相对路径而另一个是绝对路径,或者targpath无法表示为相对于basepath的路径,将返回错误。

⚠️要求 targpath 和 basepath 必须“都是相对路径”或“都是绝对路径”。

举例说明:

package main
import(
"fmt"
"path/filepath"
"log"
)
func main() {
fmt.Println(filepath.IsAbs("/Users/user/go-learning/test.txt ")) //true
fmt.Println(filepath.IsAbs("./test.txt ")) //false
abs, _ := filepath.Abs("./test.txt ")
fmt.Println(abs) ///Users/user/go-learning/test.txt
paths := []string{
"/Users/user/go-learning/stacker",
"/Users/user/go",
"./stacker",
}
base := "/Users/user/go-learning"
for _, target := range paths {
rel, err := filepath.Rel(base, target)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%q : %q %v\n", target, rel, err)
}
//返回:
// "/Users/user/go-learning/stacker" : "stacker" <nil>
// "/Users/user/go" : "../go" <nil>
// 2019/01/24 09:32:57 Rel: can't make ./stacker relative to /Users/user/go-learning
// exit status 1 }

上面可见当两者不都是绝对或相对路径时会报错并退出

如果将两个都写成相对路径,就成功了:

package main
import(
"fmt"
"path/filepath"
"log"
)
func main() {
target := "./stacker"
base := "./"
rel, err := filepath.Rel(base, target)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%q : %q %v\n", target, rel, err)
}

返回:

userdeMBP:go-learning user$ go run test.go
"./stacker" : "stacker" <nil>

7》func SplitList

func SplitList(path string) []string

将PATH或GOPATH等环境变量里的多个路径分割开(这些路径被OS特定的表分隔符连接起来)。与strings.Split函数的不同之处是:对"",SplitList返回[]string{},而strings.Split返回[]string{""}。

8》func Split

func Split(path string) (dir, file string)

Split函数将路径从最后一个路径分隔符后面位置分隔为两个部分(dir和file)并返回。如果路径中没有路径分隔符,函数返回值dir会设为空字符串,file会设为path。两个返回值满足path == dir+file。

举例:

package main
import(
"fmt"
"path/filepath"
)
func main() {
fmt.Println(filepath.SplitList("/Library/Java/JavaVirtualMachines/jdk-10.0.1.jdk/Contents/Home/bin:/usr/local/bin:/Users/user/go/bin:/usr/local/mysql/bin:"))
dir, file := filepath.Split("/Library/Java/JavaVirtualMachines/jdk-10.0.1.jdk/Contents/Home/bin:/usr/local/bin:/Users/user/go/bin:/usr/local/mysql/bin:")
fmt.Println(dir, file)
fmt.Println(filepath.SplitList(""))
dir, file = filepath.Split("")
fmt.Println(dir, file)
}

返回:

userdeMBP:go-learning user$ go run test.go
[/Library/Java/JavaVirtualMachines/jdk-10.0..jdk/Contents/Home/bin /usr/local/bin /Users/user/go/bin /usr/local/mysql/bin ]
/Library/Java/JavaVirtualMachines/jdk-10.0..jdk/Contents/Home/bin:/usr/local/bin:/Users/user/go/bin:/usr/local/mysql/ bin:
[] userdeMBP:go-learning user$

9》func Join

func Join(elem ...string) string

Join函数可以将任意数量的路径元素放入一个单一路径里,会根据需要添加路径分隔符。结果是经过简化的,所有的空字符串元素会被忽略。

举例:

package main
import(
"fmt"
"path/filepath"
)
func main() {
fmt.Println(filepath.Join("Users", "user", "go-learning"))//Users/user/go-learning }

10》func FromSlash

func FromSlash(path string) string

FromSlash函数将path中的斜杠('/')替换为路径分隔符(Unix的为'/',所以结果没有变化)并返回替换结果,多个斜杠会替换为多个路径分隔符。

11》func  ToSlash

func ToSlash(path string) string

ToSlash函数将path中的路径分隔符(Unix的为'/',所以结果没有变化)替换为斜杠('/')并返回替换结果,多个路径分隔符会替换为多个斜杠。

举例(因为我的系统是Unix,所以路径分隔符就是'/',所以结果并没有变化):

package main
import(
"fmt"
"path/filepath"
)
func main() {
fromSlash := filepath.FromSlash("http://www.baidu.com/p")
fmt.Println(fromSlash)
fmt.Println(filepath.ToSlash("/usr/bin:/bin:/usr/sbin:/sbin"))
}

返回:

userdeMBP:go-learning user$ go run test.go
http://www.baidu.com/p
/usr/bin:/bin:/usr/sbin:/sbin

12》func VolumeName

func VolumeName(path string) (v string)

VolumeName函数返回最前面的卷名。如Windows系统里提供参数"C:\foo\bar"会返回"C:";Unix/linux系统的"\\host\share\foo"会返回"\\host\share";其他平台会返回""。

13》func Dir

func Dir(path string) string

Dir返回路径除去最后一个路径元素的部分,即该路径最后一个元素所在的目录。在使用Split去掉最后一个元素后,会简化路径并去掉末尾的斜杠。如果路径是空字符串,会返回".";如果路径由1到多个路径分隔符后跟0到多个非路径分隔符字符组成,会返回单个路径分隔符;其他任何情况下都不会返回以路径分隔符结尾的路径。

14》func Base

func Base(path string) string

Base函数返回路径的最后一个元素。在提取元素前会求掉末尾的路径分隔符。如果路径是"",会返回".";如果路径是只有一个斜杆构成,会返回单个路径分隔符。

15》Ext

Ext函数返回path文件扩展名。返回值是路径最后一个路径元素的最后一个'.'起始的后缀(包括'.')。如果该元素没有'.'会返回空字符串。

举例:

package main
import(
"fmt"
"path/filepath"
)
func main() {
fmt.Println(filepath.Dir("/Users/user/go-learning/test.go"))
fmt.Println(filepath.Base("/Users/user/go-learning/test.go"))
fmt.Println(filepath.Ext("/Users/user/go-learning/test.go"))
dir, file := filepath.Split("/Users/user/go-learning/test.go")
fmt.Printf("%q : %q\n", dir, file)
}

返回:

userdeMBP:go-learning user$ go run test.go
/Users/user/go-learning
test.go
.go
"/Users/user/go-learning/" : "test.go"

可见Split()也能得到类似的效果,只是目录后还是会跟着一个路径分隔符'/'

16》func clean

func Clean(path string) string

Clean函数通过单纯的词法操作返回和path代表同一地址的最短路径。

它会不断的依次应用如下的规则,直到不能再进行任何处理:

. 将连续的多个路径分隔符替换为单个路径分隔符
. 剔除每一个.路径名元素(代表当前目录)
. 剔除每一个路径内的..路径名元素(代表父目录)和它前面的非..路径名元素
. 剔除开始一个根路径的..路径名元素,即将路径开始处的"/.."替换为"/"(假设路径分隔符是'/')

返回的路径只有其代表一个根地址时才以路径分隔符结尾,如Unix的"/"或Windows的`C:\`。

如果处理的结果是空字符串,Clean会返回"."。

举例:

package main
import(
"fmt"
"path/filepath"
)
func main() {
paths := []string{
"/Users/user/go-learning/../go",
"./stacker",
"/Users/user/go-learning/../..",
}
for _, path := range paths{
fmt.Println(filepath.Clean(path))
}
}

返回:

userdeMBP:go-learning user$ go run test.go
/Users/user/go
stacker
/Users

所以其实使用简单的说法就是将一个复杂的路径变成其等价的最简单的表示形式

17》func EvalSymlinks

func EvalSymlinks(path string) (string, error)

EvalSymlinks函数返回path指向的符号链接(软链接)所包含的路径。如果path和返回值都是相对路径,会相对于当前目录;除非两个路径其中一个是绝对路径。

18》func Match

func Match(pattern, name string) (matched bool, err error)

如果name匹配shell文件命名模式pattern,则返回true。命名模式pattern为:

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系统中,不能进行转义:'\\'被视为路径分隔符。

举例:

package main
import(
"fmt"
"path/filepath"
)
func main() {
fmt.Println(filepath.Match("*", "a")); //true <nil>
fmt.Println(filepath.Match("*", "C:/a/b/c")); //false <nil>
fmt.Println(filepath.Match("\\b", "b")); //true <nil>
fmt.Println(filepath.Match("ab[c]", "abc")); //true <nil>
fmt.Println(filepath.Match("[a-c]", "abc"));//false <nil>,false是因为[a-c]只匹配一个
fmt.Println(filepath.Match("[a-c][a-c][a-c]", "abc"));//true <nil>这样就对了
fmt.Println(filepath.Match("[^a-c]bc", "abc"));//false <nil>
fmt.Println(filepath.Match("[^a-c]", "")); //false <nil>
}

其他例子:

var matchTests = []MatchTest{
{"abc", "abc", true, nil},
{"*", "abc", true, nil},
{"*c", "abc", true, nil},
{"a*", "a", true, nil},
{"a*", "abc", true, nil},
{"a*", "ab/c", false, nil},
{"a*/b", "abc/b", true, nil},
{"a*/b", "a/c/b", false, nil},
{"a*b*c*d*e*/f", "axbxcxdxe/f", true, nil},
{"a*b*c*d*e*/f", "axbxcxdxexxx/f", true, nil},
{"a*b*c*d*e*/f", "axbxcxdxe/xxx/f", false, nil},
{"a*b*c*d*e*/f", "axbxcxdxexxx/fff", false, nil},
{"a*b?c*x", "abxbbxdbxebxczzx", true, nil},
{"a*b?c*x", "abxbbxdbxebxczzy", false, nil},
{"ab[c]", "abc", true, nil},
{"ab[b-d]", "abc", true, nil},
{"ab[e-g]", "abc", false, nil},
{"ab[^c]", "abc", false, nil},
{"ab[^b-d]", "abc", false, nil},
{"ab[^e-g]", "abc", true, nil},
{"a\\*b", "a*b", true, nil},
{"a\\*b", "ab", false, nil},
{"a?b", "a☺b", true, nil},
{"a[^a]b", "a☺b", true, nil},
{"a???b", "a☺b", false, nil},
{"a[^a][^a][^a]b", "a☺b", false, nil},
{"[a-ζ]*", "α", true, nil},
{"*[a-ζ]", "A", false, nil},
{"a?b", "a/b", false, nil},
{"a*b", "a/b", false, nil},
{"[\\]a]", "]", true, nil},
{"[\\-]", "-", true, nil},
{"[x\\-]", "x", true, nil},
{"[x\\-]", "-", true, nil},
{"[x\\-]", "z", false, nil},
{"[\\-x]", "x", true, nil},
{"[\\-x]", "-", true, nil},
{"[\\-x]", "a", false, nil},
{"[]a]", "]", false, ErrBadPattern},
{"[-]", "-", false, ErrBadPattern},
{"[x-]", "x", false, ErrBadPattern},
{"[x-]", "-", false, ErrBadPattern},
{"[x-]", "z", false, ErrBadPattern},
{"[-x]", "x", false, ErrBadPattern},
{"[-x]", "-", false, ErrBadPattern},
{"[-x]", "a", false, ErrBadPattern},
{"\\", "a", false, ErrBadPattern},
{"[a-b-c]", "a", false, ErrBadPattern},
{"[", "a", false, ErrBadPattern},
{"[^", "a", false, ErrBadPattern},
{"[^bc", "a", false, ErrBadPattern},
{"a[", "a", false, nil},
{"a[", "ab", false, ErrBadPattern},
{"*x", "xxx", true, nil},
}

19》func Glob

func Glob(pattern string) (matches []string, err error)

Glob函数返回所有匹配模式匹配字符串pattern的文件或者nil(如果没有匹配的文件)。pattern的语法和Match函数相同。pattern可以描述多层的名字,如/usr/*/bin/ed(假设路径分隔符是'/')。

举例:

package main
import(
"fmt"
"path/filepath"
"log"
)
func main() {
//返回指定文件下以test开头的文件
matches, err := filepath.Glob("/Users/user/go-learning/test*") //[/Users/user/go-learning/test.go /Users/user/go-learning/test.txt /Users/user/go-learning/testCreate.txt]
if err != nil{
log.Fatal(err)
}
fmt.Println(matches) }

go标准库的学习-path/filepath的更多相关文章

  1. go标准库的学习-net/http

    参考:https://studygolang.com/pkgdoc 概念解释: request:用户请求的信息,用来解析用户的请求信息,包括post.get.cookie.url等信息 respons ...

  2. go标准库的学习-database/sql

    参考:https://studygolang.com/pkgdoc 导入方式: import "database/sql" sql包提供了保证SQL或类SQL数据库的泛用接口. 使 ...

  3. go标准库的学习-crypto/md5

    参考:https://studygolang.com/pkgdoc 导入方式: import "crypto/md5" md5包实现了MD5哈希算法,参见RFC 1321. Con ...

  4. go标准库的学习-crypto/sha1

    参考:https://studygolang.com/pkgdoc 导入方式: import "crypto/sha1" sha1包实现了SHA1哈希算法,参见RFC 3174. ...

  5. go标准库的学习-crypto/sha256

    参考:https://studygolang.com/pkgdoc 导入方式: import "crypto/sha256" sha256包实现了SHA224和SHA256哈希算法 ...

  6. python 标准库基础学习之开发工具部分1学习

    #2个标准库模块放一起学习,这样减少占用地方和空间#标准库之compileall字节编译源文件import compileall,re,sys#作用是查找到python文件,并把它们编译成字节码表示, ...

  7. python linecache标准库基础学习

    #python标准库基础之:linecacge:高效读取文本文件#说明与作用"""可以从文件或者导入python模块获取文件,维护一个结果缓存,从而可以更高效地从相同文件 ...

  8. python calendar标准库基础学习

    # -*- coding: utf-8 -*-# 作者:新手__author__ = 'Administrator'#标准库:日期时间基础学习:calendar:处理日期#例1import calen ...

  9. 《C标准库》学习笔记整理

    简介 <C标准库>书中对 C 标准库中的 15 个头文件的内容进行了详细的介绍,包括各头文件设计的背景知识.头文件中的内容.头文件中定义的函数和变量的使用.实现.测试等. 我学习此书的目的 ...

随机推荐

  1. js控制随机数生成概率代码实例

    基本思路:把Math.random()js随机数生成的数看着百分比,然后定义每个整数值取值范围. 具体内容如下,供大家参考 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ...

  2. css 表单标签两端对齐

    来自:http://demo.doyoe.com/css3/justify/justify-form.htm  侵删 <!DOCTYPE html> <html lang=" ...

  3. jQuery 对AMD的支持(Require.js中如何使用jQuery)

    AMD 模块 AMD(异步模块定义,Asynchronous Module Definition)格式总体的目标是为现在的开发者提供一个可用的模块化 JavaScript 的解决方案. AMD 模块格 ...

  4. cf55D. Beautiful numbers(数位dp)

    题意 题目链接 Sol 看到这种题就不难想到是数位dp了. 一个很显然的性质是一个数若能整除所有位数上的数,则一定能整除他们的lcm. 根据这个条件我们不难看出我们只需要记录每个数对所有数的lcm(也 ...

  5. SAP WM 有无保存WM Level历史库存的Table?

    SAP WM 有无保存WM Level历史库存的Table? 前日下班回家的路上,收到一个前客户内部顾问同行发过来的微信,问我在SAP系统里哪个表是用来存储WM Level历史库存的. 这个问题问住了 ...

  6. 嵌套RecyclerView左右滑动替代自定义view

    以前的左右滑动效果采用自定义scrollview或者linearlayout来实现,recyclerview可以很好的做这个功能,一般的需求就是要么一个独立的左右滑动效果,要么在一个列表里的中间部分一 ...

  7. DES数据解密

    /// <summary> /// DES数据解密 /// </summary> /// <param name="targetValue">& ...

  8. git 入门教程之安装 git

    安装 git git 目前支持 Linux/Unix.Solaris.Mac和 Windows 平台上运行,根据自身环境选择安装. Linux 系统 linux 系统安装软件大致有两种途径,一种是利用 ...

  9. matlab练习程序(求向量间的旋转矩阵与四元数)

    问题是这样,如果我们知道两个向量v1和v2,计算从v1转到v2的旋转矩阵和四元数,由于旋转矩阵和四元数可以互转,所以我们先计算四元数. 我们可以认为v1绕着向量u旋转θ​角度到v2,u垂直于v1-v2 ...

  10. PyCharm 在PyCharm中使用GitHub

    PyCharm是当前进行Python开发,尤其是Django开发最好的IDE,GitHub是程序员的圣地,几乎人人都在用,就不详细介绍两者了. 本文假设你对PyCharm和Github都有一定的了解, ...