软件包filepath实现了实用程序例程,用于以与目标操作系统定义的文件路径兼容的方式来处理文件名路径。

文件路径包使用正斜杠或反斜杠,具体取决于操作系统。若要处理诸如URL之类的路径,无论使用什么操作系统,该路径始终使用正斜杠,请参阅路径包。
——————————————————————————————
路径分隔符转换:

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

Abs

  1. // func Abs(path string) (string, error)
  2. // 返回所给目录的绝对路径
  3. package main
  4. import (
  5. "fmt"
  6. "path/filepath"
  7. )
  8. func main() {
  9. // 返回所给目录的绝对路径
  10. s1, _ := filepath.Abs("./a/b")
  11. fmt.Println(s1)
  12. fmt.Println(filepath.Abs(s1)) // 不同系统显示不一样
  13. s2 := "/root/a/b/c"
  14. s3 := "a/b/v/"
  15. fmt.Println(filepath.IsAbs(s1)) // true
  16. fmt.Println(filepath.IsAbs(s2)) // true
  17. fmt.Println(filepath.IsAbs(s3)) // false
  18. }
  19. /*
  20. $ go run Abs.go
  21. /Users/jordan/GolandProjects/LearnGoProject/go-new-course/day06-20200516/filepath/a/b
  22. /Users/jordan/GolandProjects/LearnGoProject/go-new-course/day06-20200516/filepath/a/b <nil>
  23. true
  24. true
  25. false
  26. */

IsAbs

  1. // 判断路径是否为绝对路径
  2. // IsAbs(path string) bool
  3. package main
  4. import (
  5. "fmt"
  6. "path/filepath"
  7. )
  8. func main() {
  9. fmt.Println("On Unix:")
  10. fmt.Println("1: ", filepath.IsAbs("/home/gopher"))
  11. fmt.Println("2: ", filepath.IsAbs(".bashrc"))
  12. fmt.Println("3: ", filepath.IsAbs(".."))
  13. fmt.Println("4: ", filepath.IsAbs("."))
  14. fmt.Println("5: ", filepath.IsAbs("/"))
  15. fmt.Println("6: ", filepath.IsAbs(""))
  16. }
  17. /*
  18. $ go run IsAbs.go
  19. On Unix:
  20. 1: true
  21. 2: false
  22. 3: false
  23. 4: false
  24. 5: true
  25. 6: false
  26. */

Base

  1. // func Base(path string) string
  2. // 获取 path 中最后一个分隔符之后的部分(不包含分隔符)
  3. // Split(path string) (dir, file string)
  4. // 获取 path 中最后一个分隔符前后的两部分,之前包含分隔符,之后不包含分隔符
  5. // Ext(path string) string
  6. // 获取路径字符串中的文件扩展名
  7. package main
  8. import (
  9. "fmt"
  10. "path/filepath"
  11. )
  12. func main() {
  13. fmt.Println("On Unix:")
  14. fmt.Println(filepath.Base("/foo/bar/baz.js"))
  15. fmt.Println(filepath.Base("/foo/bar/baz"))
  16. fmt.Println(filepath.Base("/foo/bar/baz/"))
  17. fmt.Println(filepath.Base("dev.txt"))
  18. fmt.Println(filepath.Base("../todo.txt"))
  19. fmt.Println(filepath.Base(".."))
  20. fmt.Println(filepath.Base("."))
  21. fmt.Println(filepath.Base("/"))
  22. fmt.Println(filepath.Base(""))
  23. }
  24. /*
  25. $ go run Base.go
  26. On Unix:
  27. baz.js
  28. baz
  29. baz
  30. dev.txt
  31. todo.txt
  32. ..
  33. .
  34. /
  35. .
  36. */

Clean

  1. // 清理路径中的多余字符,比如 /// 或 ../ 或 ./
  2. // Clean(path string) string
  3. package main
  4. import (
  5. "fmt"
  6. "path/filepath"
  7. )
  8. func main() {
  9. // Linux为例
  10. s := filepath.Clean("a/./b/:::/..// /c/..////d///")
  11. fmt.Println("1: ", s)
  12. //返回等价的最短路径
  13. //1.用一个斜线替换多个斜线
  14. fmt.Println("2: ", filepath.Clean("/.../..../////abc/abc"))
  15. //2.清除当前路径.
  16. fmt.Println("3: ", filepath.Clean("./1.txt"))
  17. //3.清除内部的..和他前面的元素
  18. fmt.Println("4: ", filepath.Clean("C:/a/b/../c"))
  19. //4.以/..开头的,变成/
  20. fmt.Println("5: ", filepath.Clean("/../1.txt"))
  21. }
  22. /*
  23. $ go run Clean.go
  24. 1: a/b/ /d
  25. 2: /.../..../abc/abc
  26. 3: 1.txt
  27. 4: C:/a/c
  28. 5: /1.txt
  29. */

Dir

  1. // Dir(path string) string
  2. // 获取 path 中最后一个分隔符之前的部分(不包含分隔符)
  3. package main
  4. import (
  5. "fmt"
  6. "path/filepath"
  7. )
  8. func main() {
  9. fmt.Println("On Unix:")
  10. fmt.Println(filepath.Dir("/foo/bar/baz.js"))
  11. fmt.Println(filepath.Dir("/foo/bar/baz"))
  12. fmt.Println(filepath.Dir("/foo/bar/baz/"))
  13. fmt.Println(filepath.Dir("/dirty//path///"))
  14. fmt.Println(filepath.Dir("dev.txt"))
  15. fmt.Println(filepath.Dir("../todo.txt"))
  16. fmt.Println(filepath.Dir(".."))
  17. fmt.Println(filepath.Dir("."))
  18. fmt.Println(filepath.Dir("/"))
  19. fmt.Println(filepath.Dir(""))
  20. }
  21. /*
  22. $ go run DIr.go
  23. On Unix:
  24. /foo/bar
  25. /foo/bar
  26. /foo/bar/baz
  27. /dirty/path
  28. .
  29. ..
  30. .
  31. .
  32. /
  33. .
  34. */

Ext

  1. // Ext(path string) string
  2. // 获取路径字符串中的文件扩展名
  3. package main
  4. import (
  5. "fmt"
  6. "path/filepath"
  7. )
  8. func main() {
  9. fmt.Printf("No dots: %q\n", filepath.Ext("index"))
  10. fmt.Printf("One dot: %q\n", filepath.Ext("index.js"))
  11. fmt.Printf("Two dots: %q\n", filepath.Ext("main.test.js"))
  12. }
  13. /*
  14. $ go run Ext.go
  15. No dots: ""
  16. One dot: ".js"
  17. Two dots: ".js"
  18. */

FromSlash-ToSlash

  1. // 下面两个函数主要用于将 Windows 路径分隔符转换为 Linux 路径分隔符,处理完后再转换回去,只在 Windows 中有用,在 Linux 中没必要:
  2. // 将 path 中平台相关的路径分隔符转换为 '/'
  3. // ToSlash(path string) string
  4. // 将 path 中的 '/' 转换为系统相关的路径分隔符
  5. // FromSlash(path string) string
  6. package main
  7. import (
  8. "fmt"
  9. "net/url"
  10. "os"
  11. "path/filepath"
  12. )
  13. func main() {
  14. s := "http://www.site.com/a/b/c/d"
  15. u, _ := url.Parse(s)
  16. fmt.Println(u)
  17. s = u.Path
  18. fmt.Println(s)
  19. // 下面这句用于 Windows 系统
  20. s = filepath.FromSlash(s)
  21. fmt.Println(s)
  22. // 创建目录试试
  23. if err := os.MkdirAll(s[1:], 0777); err != nil {
  24. fmt.Println(err)
  25. }
  26. // 下面这句用于 Windows 系统
  27. s = filepath.ToSlash(s)
  28. fmt.Println(s)
  29. }
  30. /*
  31. $ go run FromSlash.go
  32. http://www.site.com/a/b/c/d
  33. /a/b/c/d
  34. /a/b/c/d
  35. /a/b/c/d
  36. */

Glob

  1. // 列出与指定的模式 pattern 完全匹配的文件或目录(匹配原则同match)
  2. // Glob(pattern string) (matches []string, err error)
  3. package main
  4. import (
  5. "fmt"
  6. "path/filepath"
  7. )
  8. func main() {
  9. // 列出 filepath 的子目录中所包含的以 ba(忽略大小写)开头的项目
  10. list, err := filepath.Glob("/Users/jordan/GolandProjects/LearnGoProject/go-new-course/day06-20200516/*/[Bb]*")
  11. if err != nil {
  12. fmt.Println(err)
  13. }
  14. for _, v := range list {
  15. fmt.Println(v)
  16. }
  17. }
  18. /*
  19. $ go run Glob.go
  20. /Users/jordan/GolandProjects/LearnGoProject/go-new-course/day06-20200516/a/b
  21. /Users/jordan/GolandProjects/LearnGoProject/go-new-course/day06-20200516/filepath/Base.go
  22. /Users/jordan/GolandProjects/LearnGoProject/go-new-course/day06-20200516/test/b.go
  23. /Users/jordan/GolandProjects/LearnGoProject/go-new-course/day06-20200516/test/b.txt
  24. */

Join

  1. // 将 elem 中的多个元素合并为一个路径,忽略空元素,清理多余字符。
  2. // Join(elem ...string) string
  3. package main
  4. import (
  5. "fmt"
  6. "path/filepath"
  7. )
  8. func main() {
  9. fmt.Println("On Unix:")
  10. fmt.Println("1: ", filepath.Join("a", "b", "c"))
  11. fmt.Println("2: ", filepath.Join("a", "b/c"))
  12. fmt.Println("3: ", filepath.Join("a/b", "c"))
  13. fmt.Println("4: ", filepath.Join("a/b", "/c"))
  14. }
  15. /*
  16. $ go run Join.go
  17. On Unix:
  18. 1: a/b/c
  19. 2: a/b/c
  20. 3: a/b/c
  21. 4: a/b/c
  22. */

Match

  1. // 判断 name 是否和指定的模式 pattern 完全匹配
  2. // Match(pattern, name string) (matched bool, err error)
  3. // pattern 规则如下:
  4. // 可以使用 ? 匹配单个任意字符(不匹配路径分隔符)。
  5. // 可以使用 * 匹配 0 个或多个任意字符(不匹配路径分隔符)。
  6. // 可以使用 [] 匹配范围内的任意一个字符(可以包含路径分隔符)。
  7. // 可以使用 [^] 匹配范围外的任意一个字符(无需包含路径分隔符)。
  8. // [] 之内可以使用 - 表示一个区间,比如 [a-z] 表示 a-z 之间的任意一个字符。
  9. // 反斜线用来匹配实际的字符,比如 \* 匹配 *,\[ 匹配 [,\a 匹配 a 等等。
  10. // [] 之内可以直接使用 [ * ?,但不能直接使用 ] -,需要用 \]、\- 进行转义。
  11. package main
  12. import (
  13. "fmt"
  14. "path/filepath"
  15. )
  16. func main() {
  17. fmt.Println("On Unix:")
  18. fmt.Println(filepath.Match("/home/catch/*", "/home/catch/foo")) // true
  19. fmt.Println(filepath.Match("/home/catch/*", "/home/catch/foo/bar")) // false
  20. fmt.Println(filepath.Match("/home/?opher", "/home/gopher")) // true
  21. fmt.Println(filepath.Match("/home/\\*", "/home/*")) // true
  22. fmt.Println(filepath.Match(`???`, `abc`)) // true
  23. fmt.Println(filepath.Match(`???`, `abcd`)) // false
  24. fmt.Println(filepath.Match(`*`, `abc`)) // true
  25. fmt.Println(filepath.Match(`*`, ``)) // true
  26. fmt.Println(filepath.Match(`a*`, `abc`)) // true
  27. fmt.Println(filepath.Match(`???\\???`, `abc\def`)) // true
  28. fmt.Println(filepath.Match(`???/???`, `abc/def`)) // true
  29. fmt.Println(filepath.Match(`/*/*/*/`, `/a/b/c/`)) // true
  30. fmt.Println(filepath.Match(`[aA][bB][cC]`, `aBc`)) // true
  31. fmt.Println(filepath.Match(`[^aA]*`, `abc`)) // false
  32. fmt.Println(filepath.Match(`[a-z]*`, `a+b`)) // true
  33. fmt.Println(filepath.Match(`\[*\]`, `[a+b]`)) // true
  34. fmt.Println(filepath.Match(`[[\]]*[[\]]`, `[]`)) // true
  35. }

Rel

  1. // 获取 targpath 相对于 basepath 的路径。
  2. // 要求 targpath 和 basepath 必须“都是相对路径”或“都是绝对路径”。
  3. // Rel(basepath, targpath string) (string, error)
  4. package main
  5. import (
  6. "fmt"
  7. "path/filepath"
  8. )
  9. func main() {
  10. //例1:
  11. paths := []string{
  12. "/a/b/c",
  13. "/b/c",
  14. "./b/c",
  15. }
  16. base := "/a"
  17. fmt.Println("On Unix:")
  18. for _, p := range paths {
  19. rel, err := filepath.Rel(base, p)
  20. fmt.Printf("%q: %q %v\n", p, rel, err)
  21. }
  22. /*
  23. On Unix:
  24. "/a/b/c": "b/c" <nil>
  25. "/b/c": "../b/c" <nil>
  26. "./b/c": "" Rel: can't make ./b/c relative to /a
  27. */
  28. //例2:
  29. // 都是绝对路径
  30. s, err := filepath.Rel(`/a/b/c`, `/a/b/c/d/e`)
  31. fmt.Println(s, err) // d/e <nil>
  32. // 都是相对路径
  33. s, err = filepath.Rel(`a/b/c`, `a/b/c/d/e`)
  34. fmt.Println(s, err) // d/e <nil>
  35. // 一个绝对一个相对
  36. s, err = filepath.Rel(`/a/b/c`, `a/b/c/d/e`)
  37. fmt.Println(s, err)
  38. // Rel: can't make a/b/c/d/e relative to /a/b/c
  39. // 一个相对一个绝对
  40. s, err = filepath.Rel(`a/b/c`, `/a/b/c/d/e`)
  41. fmt.Println(s, err)
  42. // Rel: can't make /a/b/c/d/e relative to a/b/c
  43. // 从 `a/b/c` 进入 `a/b/d/e`,只需要进入 `../d/e` 即可
  44. s, err = filepath.Rel(`a/b/c`, `a/b/d/e`)
  45. fmt.Println(s, err) // ../d/e <nil>
  46. }

Split

  1. // 获取 path 中最后一个分隔符前后的两部分
  2. // 之前包含分隔符,之后不包含分隔符
  3. // Split(path string) (dir, file string)
  4. package main
  5. import (
  6. "fmt"
  7. "path/filepath"
  8. )
  9. func main() {
  10. paths := []string{
  11. "/home/arnie/amelia.jpg",
  12. "/mnt/photos/",
  13. "rabbit.jgp",
  14. "/usr/local//go",
  15. }
  16. fmt.Println("On Unix:")
  17. for _, path := range paths {
  18. dir, file := filepath.Split(path)
  19. fmt.Printf("input: %q\n\tdir: %q\n\tfile: %q\n", path, dir, file)
  20. }
  21. }
  22. /*
  23. $ go run Split.go
  24. On Unix:
  25. input: "/home/arnie/amelia.jpg"
  26. dir: "/home/arnie/"
  27. file: "amelia.jpg"
  28. input: "/mnt/photos/"
  29. dir: "/mnt/photos/"
  30. file: ""
  31. input: "rabbit.jgp"
  32. dir: ""
  33. file: "rabbit.jgp"
  34. input: "/usr/local//go"
  35. dir: "/usr/local//"
  36. file: "go"
  37. */

SplitList

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

Walk-WalkFunc

  1. // 遍历指定目录(包括子目录),对遍历到的项目用 walkFn 函数进行处理。
  2. // Walk遍历以root为根的文件树,为树中的每个文件或目录(包括root)调用walkFn。
  3. // walkFn会过滤访问文件和目录时出现的所有错误。这些文件以词法顺序进行遍历,这使输出具有确定性,但是这意味着对于非常大的目录,遍历可能效率不高。walk不能找到链接的文件
  4. // Walk(root string, walkFn WalkFunc) error
  5. // 文件处理函数定义如下,如果 WalkFunc 返回 nil,则 Walk 函数继续遍历,如果返回 SkipDir,则 Walk 函数会跳过当前目录(如果当前遍历到的是文件,则同时跳过后续文件及子目录),继续遍历下一个目录。
  6. // 如果返回其它错误,则 Walk 函数会中止遍历过程。
  7. // 在 Walk 遍历过程中,如果遇到错误,则会将错误通过 err 传递给WalkFunc 函数,同时 Walk 会跳过出错的项目,继续处理后续项目。
  8. //type WalkFunc func(path string, info os.FileInfo, err error) error
  9. package main
  10. import (
  11. "fmt"
  12. "io/ioutil"
  13. "os"
  14. "path/filepath"
  15. )
  16. func prepareTestDirTree(tree string) (string, error) {
  17. tmpDir, err := ioutil.TempDir("", "")
  18. if err != nil {
  19. return "", fmt.Errorf("error creating temp directory: %v\n", err)
  20. }
  21. err = os.MkdirAll(filepath.Join(tmpDir, tree), 0755)
  22. if err != nil {
  23. os.RemoveAll(tmpDir)
  24. return "", err
  25. }
  26. return tmpDir, nil
  27. }
  28. func main() {
  29. tmpDir, err := prepareTestDirTree("dir/to/walk/skip")
  30. if err != nil {
  31. fmt.Printf("unable to create test dir tree: %v\n", err)
  32. return
  33. }
  34. defer os.RemoveAll(tmpDir)
  35. os.Chdir(tmpDir)
  36. subDirToSkip := "skip"
  37. fmt.Println("On Unix: ")
  38. err = filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
  39. if err != nil {
  40. fmt.Printf("prevent panic by handing failure accessing a path %q: %v\n", path, err)
  41. return err
  42. }
  43. if info.IsDir() && info.Name() == subDirToSkip {
  44. fmt.Printf("skipping a dir without errors: %+v \n", info.Name())
  45. return filepath.SkipDir
  46. }
  47. fmt.Printf("visited file or dir:%q\n", path)
  48. return nil
  49. })
  50. if err != nil {
  51. fmt.Printf("error walking the path %q: %v\n", tmpDir, err)
  52. return
  53. }
  54. }
  55. /*
  56. $ go run Walk.go
  57. On Unix:
  58. visited file or dir:"."
  59. visited file or dir:"dir"
  60. visited file or dir:"dir/to"
  61. visited file or dir:"dir/to/walk"
  62. skipping a dir without errors: skip
  63. */