zoukankan      html  css  js  c++  java
  • go语言-golang包-path/filepath包

    path/filepath
    软件包filepath实现了实用程序例程,用于以与目标操作系统定义的文件路径兼容的方式来处理文件名路径。
    
    文件路径包使用正斜杠或反斜杠,具体取决于操作系统。若要处理诸如URL之类的路径,无论使用什么操作系统,该路径始终使用正斜杠,请参阅路径包。
    ------------------------------------------------------------ 
    路径分隔符转换:

    const (  
      Separator  = os.PathSeparator  // 路径分隔符(分隔路径元素)  
      ListSeparator = os.PathListSeparator // 路径列表分隔符(分隔多个路径)
    )
    ------------------------------------------------------------ 

    Abs

    // func Abs(path string) (string, error)
    // 返回所给目录的绝对路径
    package main
    
    import (
        "fmt"
        "path/filepath"
    )
    
    func main() {
        // 返回所给目录的绝对路径
        s1, _ := filepath.Abs("./a/b")
        fmt.Println(s1)
        fmt.Println(filepath.Abs(s1)) // 不同系统显示不一样
        s2 := "/root/a/b/c"
        s3 := "a/b/v/"
        fmt.Println(filepath.IsAbs(s1)) // true
        fmt.Println(filepath.IsAbs(s2)) // true
        fmt.Println(filepath.IsAbs(s3)) // false
    
    }
    
    /*
    $ go run Abs.go
    /Users/jordan/GolandProjects/LearnGoProject/go-new-course/day06-20200516/filepath/a/b
    /Users/jordan/GolandProjects/LearnGoProject/go-new-course/day06-20200516/filepath/a/b <nil>
    true
    true
    false
    
    */

    IsAbs

    // 判断路径是否为绝对路径
    // IsAbs(path string) bool
    package main
    
    import (
        "fmt"
        "path/filepath"
    )
    
    func main() {
        fmt.Println("On Unix:")
        fmt.Println("1: ", filepath.IsAbs("/home/gopher"))
        fmt.Println("2: ", filepath.IsAbs(".bashrc"))
        fmt.Println("3: ", filepath.IsAbs(".."))
        fmt.Println("4: ", filepath.IsAbs("."))
        fmt.Println("5: ", filepath.IsAbs("/"))
        fmt.Println("6: ", filepath.IsAbs(""))
    }
    
    /*
    $ go run IsAbs.go
    On Unix:
    1:  true
    2:  false
    3:  false
    4:  false
    5:  true
    6:  false
    
    */

    Base

    // func Base(path string) string
    // 获取 path 中最后一个分隔符之后的部分(不包含分隔符)
    
    // Split(path string) (dir, file string)
    // 获取 path 中最后一个分隔符前后的两部分,之前包含分隔符,之后不包含分隔符
    
    // Ext(path string) string
    // 获取路径字符串中的文件扩展名
    
    package main
    
    import (
        "fmt"
        "path/filepath"
    )
    
    func main() {
        fmt.Println("On Unix:")
        fmt.Println(filepath.Base("/foo/bar/baz.js"))
        fmt.Println(filepath.Base("/foo/bar/baz"))
        fmt.Println(filepath.Base("/foo/bar/baz/"))
        fmt.Println(filepath.Base("dev.txt"))
        fmt.Println(filepath.Base("../todo.txt"))
        fmt.Println(filepath.Base(".."))
        fmt.Println(filepath.Base("."))
        fmt.Println(filepath.Base("/"))
        fmt.Println(filepath.Base(""))
    }
    
    /*
    $ go run Base.go
    On Unix:
    baz.js
    baz
    baz
    dev.txt
    todo.txt
    ..
    .
    /
    .
    */

    Clean

    // 清理路径中的多余字符,比如 /// 或 ../ 或 ./
    // Clean(path string) string
    package main
    
    import (
        "fmt"
        "path/filepath"
    )
    
    func main() {
        // Linux为例
        s := filepath.Clean("a/./b/:::/..//  /c/..////d///")
        fmt.Println("1: ", s)
    
        //返回等价的最短路径
        //1.用一个斜线替换多个斜线
        fmt.Println("2: ", filepath.Clean("/.../..../////abc/abc"))
        //2.清除当前路径.
        fmt.Println("3: ", filepath.Clean("./1.txt"))
        //3.清除内部的..和他前面的元素
        fmt.Println("4: ", filepath.Clean("C:/a/b/../c"))
        //4.以/..开头的,变成/
        fmt.Println("5: ", filepath.Clean("/../1.txt"))
    }
    
    /*
    $ go run Clean.go
    1:  a/b/  /d
    2:  /.../..../abc/abc
    3:  1.txt
    4:  C:/a/c
    5:  /1.txt
    */

    Dir

    // Dir(path string) string
    // 获取 path 中最后一个分隔符之前的部分(不包含分隔符)
    package main
    
    import (
        "fmt"
        "path/filepath"
    )
    
    func main() {
        fmt.Println("On Unix:")
        fmt.Println(filepath.Dir("/foo/bar/baz.js"))
        fmt.Println(filepath.Dir("/foo/bar/baz"))
        fmt.Println(filepath.Dir("/foo/bar/baz/"))
        fmt.Println(filepath.Dir("/dirty//path///"))
        fmt.Println(filepath.Dir("dev.txt"))
        fmt.Println(filepath.Dir("../todo.txt"))
        fmt.Println(filepath.Dir(".."))
        fmt.Println(filepath.Dir("."))
        fmt.Println(filepath.Dir("/"))
        fmt.Println(filepath.Dir(""))
    
    }
    
    /*
    $ go run DIr.go
    On Unix:
    /foo/bar
    /foo/bar
    /foo/bar/baz
    /dirty/path
    .
    ..
    .
    .
    /
    .
    
    */

    Ext

    // Ext(path string) string
    // 获取路径字符串中的文件扩展名
    package main
    
    import (
        "fmt"
        "path/filepath"
    )
    
    func main() {
        fmt.Printf("No dots: %q
    ", filepath.Ext("index"))
        fmt.Printf("One dot: %q
    ", filepath.Ext("index.js"))
        fmt.Printf("Two dots: %q
    ", filepath.Ext("main.test.js"))
    }
    
    /*
    $ go run Ext.go
    No dots: ""
    One dot: ".js"
    Two dots: ".js"
    
    */

    FromSlash-ToSlash

    // 下面两个函数主要用于将 Windows 路径分隔符转换为 Linux 路径分隔符,处理完后再转换回去,只在 Windows 中有用,在 Linux 中没必要:
    // 将 path 中平台相关的路径分隔符转换为 '/'
    // ToSlash(path string) string
    
    // 将 path 中的 '/' 转换为系统相关的路径分隔符
    // FromSlash(path string) string
    
    package main
    
    import (
        "fmt"
        "net/url"
        "os"
        "path/filepath"
    )
    
    func main() {
        s := "http://www.site.com/a/b/c/d"
        u, _ := url.Parse(s)
        fmt.Println(u)
        s = u.Path
        fmt.Println(s)
    
        // 下面这句用于 Windows 系统
        s = filepath.FromSlash(s)
        fmt.Println(s)
    
        // 创建目录试试
        if err := os.MkdirAll(s[1:], 0777); err != nil {
            fmt.Println(err)
        }
        // 下面这句用于 Windows 系统
        s = filepath.ToSlash(s)
        fmt.Println(s)
    
    }
    
    /*
    $ go run FromSlash.go
    http://www.site.com/a/b/c/d
    /a/b/c/d
    /a/b/c/d
    /a/b/c/d
    */

    Glob

    // 列出与指定的模式 pattern 完全匹配的文件或目录(匹配原则同match)
    // Glob(pattern string) (matches []string, err error)
    package main
    
    import (
        "fmt"
        "path/filepath"
    )
    
    func main() {
        // 列出 filepath 的子目录中所包含的以 ba(忽略大小写)开头的项目
        list, err := filepath.Glob("/Users/jordan/GolandProjects/LearnGoProject/go-new-course/day06-20200516/*/[Bb]*")
        if err != nil {
            fmt.Println(err)
        }
        for _, v := range list {
            fmt.Println(v)
        }
    }
    
    /*
    $ go run Glob.go
    /Users/jordan/GolandProjects/LearnGoProject/go-new-course/day06-20200516/a/b
    /Users/jordan/GolandProjects/LearnGoProject/go-new-course/day06-20200516/filepath/Base.go
    /Users/jordan/GolandProjects/LearnGoProject/go-new-course/day06-20200516/test/b.go
    /Users/jordan/GolandProjects/LearnGoProject/go-new-course/day06-20200516/test/b.txt
    
    */

    Join

    // 将 elem 中的多个元素合并为一个路径,忽略空元素,清理多余字符。
    // Join(elem ...string) string
    
    package main
    
    import (
        "fmt"
        "path/filepath"
    )
    
    func main() {
        fmt.Println("On Unix:")
        fmt.Println("1: ", filepath.Join("a", "b", "c"))
        fmt.Println("2: ", filepath.Join("a", "b/c"))
        fmt.Println("3: ", filepath.Join("a/b", "c"))
        fmt.Println("4: ", filepath.Join("a/b", "/c"))
    }
    
    /*
    $ go run Join.go
    On Unix:
    1:  a/b/c
    2:  a/b/c
    3:  a/b/c
    4:  a/b/c
    
    */

    Match

    // 判断 name 是否和指定的模式 pattern 完全匹配
    // Match(pattern, name string) (matched bool, err error)
    // pattern 规则如下:
    // 可以使用 ? 匹配单个任意字符(不匹配路径分隔符)。
    // 可以使用 * 匹配 0 个或多个任意字符(不匹配路径分隔符)。
    // 可以使用 [] 匹配范围内的任意一个字符(可以包含路径分隔符)。
    // 可以使用 [^] 匹配范围外的任意一个字符(无需包含路径分隔符)。
    // [] 之内可以使用 - 表示一个区间,比如 [a-z] 表示 a-z 之间的任意一个字符。
    // 反斜线用来匹配实际的字符,比如 * 匹配 *,[ 匹配 [,a 匹配 a 等等。
    // [] 之内可以直接使用 [ * ?,但不能直接使用 ] -,需要用 ]、- 进行转义。
    
    package main
    
    import (
        "fmt"
        "path/filepath"
    )
    
    func main() {
        fmt.Println("On Unix:")
        fmt.Println(filepath.Match("/home/catch/*", "/home/catch/foo"))     // true
        fmt.Println(filepath.Match("/home/catch/*", "/home/catch/foo/bar")) // false
        fmt.Println(filepath.Match("/home/?opher", "/home/gopher"))         // true
        fmt.Println(filepath.Match("/home/\*", "/home/*"))                 // true
    
        fmt.Println(filepath.Match(`???`, `abc`))          // true
        fmt.Println(filepath.Match(`???`, `abcd`))         // false
        fmt.Println(filepath.Match(`*`, `abc`))            // true
        fmt.Println(filepath.Match(`*`, ``))               // true
        fmt.Println(filepath.Match(`a*`, `abc`))           // true
        fmt.Println(filepath.Match(`???\???`, `abcdef`)) // true
        fmt.Println(filepath.Match(`???/???`, `abc/def`))  // true
        fmt.Println(filepath.Match(`/*/*/*/`, `/a/b/c/`))  // true
        fmt.Println(filepath.Match(`[aA][bB][cC]`, `aBc`)) // true
        fmt.Println(filepath.Match(`[^aA]*`, `abc`))       // false
        fmt.Println(filepath.Match(`[a-z]*`, `a+b`))       // true
        fmt.Println(filepath.Match(`[*]`, `[a+b]`))      // true
        fmt.Println(filepath.Match(`[[]]*[[]]`, `[]`))   // true
    }

    Rel

    // 获取 targpath 相对于 basepath 的路径。
    // 要求 targpath 和 basepath 必须“都是相对路径”或“都是绝对路径”。
    // Rel(basepath, targpath string) (string, error)
    package main
    
    import (
        "fmt"
        "path/filepath"
    )
    
    func main() {
        //例1:
        paths := []string{
            "/a/b/c",
            "/b/c",
            "./b/c",
        }
        base := "/a"
    
        fmt.Println("On Unix:")
        for _, p := range paths {
            rel, err := filepath.Rel(base, p)
            fmt.Printf("%q: %q %v
    ", p, rel, err)
        }
        /*
            On Unix:
            "/a/b/c": "b/c" <nil>
            "/b/c": "../b/c" <nil>
            "./b/c": "" Rel: can't make ./b/c relative to /a
        */
    
        //例2:
        // 都是绝对路径
        s, err := filepath.Rel(`/a/b/c`, `/a/b/c/d/e`)
        fmt.Println(s, err) // d/e <nil>
    
        // 都是相对路径
        s, err = filepath.Rel(`a/b/c`, `a/b/c/d/e`)
        fmt.Println(s, err) // d/e <nil>
    
        // 一个绝对一个相对
        s, err = filepath.Rel(`/a/b/c`, `a/b/c/d/e`)
        fmt.Println(s, err)
        //  Rel: can't make a/b/c/d/e relative to /a/b/c
    
        // 一个相对一个绝对
        s, err = filepath.Rel(`a/b/c`, `/a/b/c/d/e`)
        fmt.Println(s, err)
        //  Rel: can't make /a/b/c/d/e relative to a/b/c
    
        // 从 `a/b/c` 进入 `a/b/d/e`,只需要进入 `../d/e` 即可
        s, err = filepath.Rel(`a/b/c`, `a/b/d/e`)
        fmt.Println(s, err) // ../d/e <nil>
    }

    Split

    // 获取 path 中最后一个分隔符前后的两部分
    // 之前包含分隔符,之后不包含分隔符
    // Split(path string) (dir, file string)
    
    package main
    
    import (
        "fmt"
        "path/filepath"
    )
    
    func main() {
        paths := []string{
            "/home/arnie/amelia.jpg",
            "/mnt/photos/",
            "rabbit.jgp",
            "/usr/local//go",
        }
        fmt.Println("On Unix:")
        for _, path := range paths {
            dir, file := filepath.Split(path)
            fmt.Printf("input: %q
    	dir: %q
    	file: %q
    ", path, dir, file)
        }
    }
    
    /*
    $ go run Split.go
    On Unix:
    input: "/home/arnie/amelia.jpg"
            dir: "/home/arnie/"
            file: "amelia.jpg"
    input: "/mnt/photos/"
            dir: "/mnt/photos/"
            file: ""
    input: "rabbit.jgp"
            dir: ""
            file: "rabbit.jgp"
    input: "/usr/local//go"
            dir: "/usr/local//"
            file: "go"
    
    */

    SplitList

    // 将路径序列 操作系统特别的连接符组成的path,通常用在PATH或者GOPARTH环境变量中, 分割为多条独立的路径。跟strings.Split不同,当传入空的字符串,SplitList会返回一个空的切片
    // SplitList(path string) []string
    
    package main
    
    import (
        "fmt"
        "path/filepath"
    )
    
    func main() {
        fmt.Println("On Unix:", filepath.SplitList("/a/b/c:/usr/bin"))
        fmt.Println("On Unix:", filepath.SplitList(""))
    }
    
    /*
    $ go run SplitList.go
    On Unix: [/a/b/c /usr/bin]
    On Unix: []
    
    */

    Walk-WalkFunc

    // 遍历指定目录(包括子目录),对遍历到的项目用 walkFn 函数进行处理。
    // Walk遍历以root为根的文件树,为树中的每个文件或目录(包括root)调用walkFn。
    // walkFn会过滤访问文件和目录时出现的所有错误。这些文件以词法顺序进行遍历,这使输出具有确定性,但是这意味着对于非常大的目录,遍历可能效率不高。walk不能找到链接的文件
    // Walk(root string, walkFn WalkFunc) error
    // 文件处理函数定义如下,如果 WalkFunc 返回 nil,则 Walk 函数继续遍历,如果返回 SkipDir,则 Walk 函数会跳过当前目录(如果当前遍历到的是文件,则同时跳过后续文件及子目录),继续遍历下一个目录。
    // 如果返回其它错误,则 Walk 函数会中止遍历过程。
    // 在 Walk 遍历过程中,如果遇到错误,则会将错误通过 err 传递给WalkFunc 函数,同时 Walk 会跳过出错的项目,继续处理后续项目。
    //type WalkFunc func(path string, info os.FileInfo, err error) error
    
    package main
    
    import (
        "fmt"
        "io/ioutil"
        "os"
        "path/filepath"
    )
    
    func prepareTestDirTree(tree string) (string, error) {
        tmpDir, err := ioutil.TempDir("", "")
        if err != nil {
            return "", fmt.Errorf("error creating temp directory: %v
    ", err)
        }
        err = os.MkdirAll(filepath.Join(tmpDir, tree), 0755)
        if err != nil {
            os.RemoveAll(tmpDir)
            return "", err
        }
        return tmpDir, nil
    }
    
    func main() {
        tmpDir, err := prepareTestDirTree("dir/to/walk/skip")
        if err != nil {
            fmt.Printf("unable to create test dir tree: %v
    ", err)
            return
        }
        defer os.RemoveAll(tmpDir)
        os.Chdir(tmpDir)
    
        subDirToSkip := "skip"
    
        fmt.Println("On Unix: ")
        err = filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
            if err != nil {
                fmt.Printf("prevent panic by handing failure accessing a path %q: %v
    ", path, err)
                return err
            }
            if info.IsDir() && info.Name() == subDirToSkip {
                fmt.Printf("skipping a dir without errors: %+v 
    ", info.Name())
                return filepath.SkipDir
            }
            fmt.Printf("visited file or dir:%q
    ", path)
            return nil
    
        })
        if err != nil {
            fmt.Printf("error walking the path %q: %v
    ", tmpDir, err)
            return
        }
    }
    
    /*
    $ go run Walk.go
    On Unix:
    visited file or dir:"."
    visited file or dir:"dir"
    visited file or dir:"dir/to"
    visited file or dir:"dir/to/walk"
    skipping a dir without errors: skip
    */
  • 相关阅读:
    POJ 1611 The Suspects
    POJ 2001 Shortest Prefixes(字典树)
    HDU 1251 统计难题(字典树 裸题 链表做法)
    G++ C++之区别
    PAT 乙级 1013. 数素数 (20)
    PAT 乙级 1012. 数字分类 (20)
    PAT 乙级 1009. 说反话 (20)
    PAT 乙级 1008. 数组元素循环右移问题 (20)
    HDU 6063 17多校3 RXD and math(暴力打表题)
    HDU 6066 17多校3 RXD's date(超水题)
  • 原文地址:https://www.cnblogs.com/malukang/p/12907945.html
Copyright © 2011-2022 走看看