Source file
src/io/fs/glob.go
1
2
3
4
5 package fs
6
7 import (
8 "path"
9 )
10
11
12 type GlobFS interface {
13 FS
14
15
16
17
18 Glob(pattern string) ([]string, error)
19 }
20
21
22
23
24
25
26
27
28
29
30
31
32
33 func Glob(fsys FS, pattern string) (matches []string, err error) {
34 if fsys, ok := fsys.(GlobFS); ok {
35 return fsys.Glob(pattern)
36 }
37
38
39 if _, err := path.Match(pattern, ""); err != nil {
40 return nil, err
41 }
42 if !hasMeta(pattern) {
43 if _, err = Stat(fsys, pattern); err != nil {
44 return nil, nil
45 }
46 return []string{pattern}, nil
47 }
48
49 dir, file := path.Split(pattern)
50 dir = cleanGlobPath(dir)
51
52 if !hasMeta(dir) {
53 return glob(fsys, dir, file, nil)
54 }
55
56
57 if dir == pattern {
58 return nil, path.ErrBadPattern
59 }
60
61 var m []string
62 m, err = Glob(fsys, dir)
63 if err != nil {
64 return
65 }
66 for _, d := range m {
67 matches, err = glob(fsys, d, file, matches)
68 if err != nil {
69 return
70 }
71 }
72 return
73 }
74
75
76 func cleanGlobPath(path string) string {
77 switch path {
78 case "":
79 return "."
80 default:
81 return path[0 : len(path)-1]
82 }
83 }
84
85
86
87
88
89 func glob(fs FS, dir, pattern string, matches []string) (m []string, e error) {
90 m = matches
91 infos, err := ReadDir(fs, dir)
92 if err != nil {
93 return
94 }
95
96 for _, info := range infos {
97 n := info.Name()
98 matched, err := path.Match(pattern, n)
99 if err != nil {
100 return m, err
101 }
102 if matched {
103 m = append(m, path.Join(dir, n))
104 }
105 }
106 return
107 }
108
109
110
111 func hasMeta(path string) bool {
112 for i := 0; i < len(path); i++ {
113 switch path[i] {
114 case '*', '?', '[', '\\':
115 return true
116 }
117 }
118 return false
119 }
120
View as plain text