英文:
How to use double star glob in Go?
问题
似乎Go
是少数几种不支持双星号("globstar")语法进行文件匹配的语言之一。至少以下代码似乎不能按预期工作:
filepath.Glob(dir + "/**/*.bundle/*.txt")
我是否对filepath
的实现有所遗漏?是否有支持此功能的库可用?
英文:
It seems like Go
is one of few languages that does not seem to understand the double star ("globstar") syntax for file globbing. At least this does not seems to work as expected:
filepath.Glob(dir + "/**/*.bundle/*.txt")
Am I missing something about the filepath
implementation?
Is there a library around that does support this?
答案1
得分: 10
filepath.Glob
的实现在底层使用了filepath.Match
。事实证明,该规范并没有涵盖非常常见的(.gitignore
、zsh
)双星号模式。虽然不完全相同,但对于我的用例,我设法通过以下这个小函数解决了这个问题:
func glob(dir string, ext string) ([]string, error) {
files := []string{}
err := filepath.Walk(dir, func(path string, f os.FileInfo, err error) error {
if filepath.Ext(path) == ext {
files = append(files, path)
}
return nil
})
return files, err
}
我仍然希望能有一个更好的实现,能够正确匹配双星号模式。
英文:
The filepath.Glob
implementation uses filepath.Match
under the hood. Turns out the specs for that do not cover the quite common (.gitignore
, zsh
) double star pattern. By no means the same - but for my use case I managed to work around it with this little function:
func glob(dir string, ext string) ([]string, error) {
files := []string{}
err := filepath.Walk(dir, func(path string, f os.FileInfo, err error) error {
if filepath.Ext(path) == ext {
files = append(files, path)
}
return nil
})
return files, err
}
I am still open for a better implementation with proper double star matching.
答案2
得分: 6
我已经写了一个小的扩展库,支持双星号通配符。使用这个目录结构:
$ find a
a
a/b
a/b/c.d
a/b/c.d/e.f
你可以使用 a/**/*.*
来匹配 a
目录下包含点的所有内容,如下所示:
<!-- language: go -->
package main
import (
"fmt"
"github.com/yargevad/filepathx"
)
func main() {
matches, err := filepathx.Glob("./a/**/*.*")
if err != nil {
panic(err)
}
for _, match := range matches {
fmt.Printf("MATCH: [%v]\n", match)
}
}
输出结果为:
$ go run example.go
MATCH: [a/b/c.d]
MATCH: [a/b/c.d/e.f]
英文:
I've written a small extension library that supports double star globbling. With this directory structure:
$ find a
a
a/b
a/b/c.d
a/b/c.d/e.f
You can use a/**/*.*
to match everything under the a
directory that contains a dot, like so:
<!-- language: go -->
package main
import (
"fmt"
"github.com/yargevad/filepathx"
)
func main() {
matches, err := filepathx.Glob("./a/**/*.*")
if err != nil {
panic(err)
}
for _, match := range matches {
fmt.Printf("MATCH: [%v]\n", match)
}
}
Which outputs:
$ go run example.go
MATCH: [a/b/c.d]
MATCH: [a/b/c.d/e.f]
答案3
得分: 0
这里有一个类似的例子。你可以传递一个回调函数来过滤文件:
package main
import (
"io/fs"
"path/filepath"
)
func glob(root string, fn func(string) bool) []string {
var files []string
filepath.WalkDir(root, func(s string, d fs.DirEntry, e error) error {
if fn(s) {
files = append(files, s)
}
return nil
})
return files
}
func main() {
files := glob(".", func(s string) bool {
return filepath.Ext(s) == ".txt"
})
for _, file := range files {
println(file)
}
}
英文:
Here is something similar. You can pass a callback to filter the files:
package main
import (
"io/fs"
"path/filepath"
)
func glob(root string, fn func(string)bool) []string {
var files []string
filepath.WalkDir(root, func(s string, d fs.DirEntry, e error) error {
if fn(s) {
files = append(files, s)
}
return nil
})
return files
}
func main() {
files := glob(".", func(s string) bool {
return filepath.Ext(s) == ".txt"
})
for _, file := range files {
println(file)
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论