go标准库的学习-path/filepath
参考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的更多相关文章
- go标准库的学习-net/http
参考:https://studygolang.com/pkgdoc 概念解释: request:用户请求的信息,用来解析用户的请求信息,包括post.get.cookie.url等信息 respons ...
- go标准库的学习-database/sql
参考:https://studygolang.com/pkgdoc 导入方式: import "database/sql" sql包提供了保证SQL或类SQL数据库的泛用接口. 使 ...
- go标准库的学习-crypto/md5
参考:https://studygolang.com/pkgdoc 导入方式: import "crypto/md5" md5包实现了MD5哈希算法,参见RFC 1321. Con ...
- go标准库的学习-crypto/sha1
参考:https://studygolang.com/pkgdoc 导入方式: import "crypto/sha1" sha1包实现了SHA1哈希算法,参见RFC 3174. ...
- go标准库的学习-crypto/sha256
参考:https://studygolang.com/pkgdoc 导入方式: import "crypto/sha256" sha256包实现了SHA224和SHA256哈希算法 ...
- python 标准库基础学习之开发工具部分1学习
#2个标准库模块放一起学习,这样减少占用地方和空间#标准库之compileall字节编译源文件import compileall,re,sys#作用是查找到python文件,并把它们编译成字节码表示, ...
- python linecache标准库基础学习
#python标准库基础之:linecacge:高效读取文本文件#说明与作用"""可以从文件或者导入python模块获取文件,维护一个结果缓存,从而可以更高效地从相同文件 ...
- python calendar标准库基础学习
# -*- coding: utf-8 -*-# 作者:新手__author__ = 'Administrator'#标准库:日期时间基础学习:calendar:处理日期#例1import calen ...
- 《C标准库》学习笔记整理
简介 <C标准库>书中对 C 标准库中的 15 个头文件的内容进行了详细的介绍,包括各头文件设计的背景知识.头文件中的内容.头文件中定义的函数和变量的使用.实现.测试等. 我学习此书的目的 ...
随机推荐
- css实现div内一段文本的两端对齐
在一个固定宽度的div内,使得P标签内的文本两端对齐: text-align: justify;text-justify:inter-ideograph; <!DOCTYPE html> ...
- @RequestMapping 详解
RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上.用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径.RequestMapping注解有六个属性,下面我们把她分 ...
- HTML DOM classList 属性
页面DOM里的每个节点上都有一个classList对象,程序员可以使用里面的方法新增.删除.修改节点上的CSS类.使用classList,程序员还可以用它来判断某个节点是否被赋予了某个CSS类. 添加 ...
- 微信小程序 text属性设置 WXSS样式
>微信小程序的布局css样式 参考自 珺L 文字 width: fit-content;font-size:20px; /*设置文字字号*/color:red; ...
- (后端)springboot 在idea中实现热部署(转)
自己用到了iIntelliJ IDEA 这个ide工具,但是和以前的工具写html,css,js直接刷新页面不同,这个需要去热部署,网上搜的解决方法: SpringBoot的web项目,在每一次修改了 ...
- Javascript数组系列四之数组的转换与排序Sort方法
今天我们继续来介绍 Javascirpt 数组中的方法,也是数组系列的第四篇文章,因为数组的方法众多,每篇文章我们都对数组的每个方法都有比较细致的描述,只要你能够从中成长一点点,那我们的目的就达到了, ...
- C#多线程图片爬虫
写了个简单的多线程图片爬虫,整理一下.数据已经爬下来了,图片URL需要自行拼接,首先从Lawyers表中取的RawData字段,RawData中有一个list字段是json格式的数据,需要的只是lis ...
- java反射笔记
反射(reflect) 1. Class对象 1.1 什么是Class对象 当JVM加载某个class文件的时候,会自动创建一个唯一的Class对象(注意:由同一个类加载器加载的class文件),这个 ...
- Oracle EBS FORM lov
存在一种情况: 一个LOV的值当前有效,因此填入保存.但突然无效后,当查询该界面时就会弹出LOV框使其修改. 解决方案: 1. 非常粗暴,不设置校验,在LOV对应的item强行将校验设置为NO. 2. ...
- Dos环境变量修改
批处理修改环境变量,修改用户变量.系统变量(全局变量),永久/临时设置环境变量.设置Java环境变量 临时环境变量 修改变量: set PATH=%Path%;%JAVA_HOME%\bin 含义:表 ...