[英]Go find files in directory recursively
I want to find all files matching a specific pattern in a directory recursively (including subdirectories).我想递归地在目录(包括子目录)中找到与特定模式匹配的所有文件。 I wrote the code to do this:
我写了代码来做到这一点:
libRegEx, e := regexp.Compile("^.+\\.(dylib)$")
if e != nil {
log.Fatal(e)
}
files, err := ioutil.ReadDir("/usr/lib")
if err != nil {
log.Fatal(err)
}
for _, f := range files {
if libRegEx.MatchString(f.Name()) {
println(f.Name())
}
}
Unfortunately, it only searches in /usr/bin
, but I also want to search for matches in its subdirectories.不幸的是,它只在
/usr/bin
搜索,但我也想在其子目录中搜索匹配项。 How can I achieve this?我怎样才能做到这一点? Thanks.
谢谢。
The standard library's filepath
package includes Walk
for exactly this purpose: "Walk walks the file tree rooted at root, calling walkFn for each file or directory in the tree, including root."标准库的文件
filepath
包包含Walk
正是为了这个目的:“Walk 遍历以根为根的文件树,为树中的每个文件或目录调用 walkFn,包括根。” For example:例如:
libRegEx, e := regexp.Compile("^.+\\.(dylib)$")
if e != nil {
log.Fatal(e)
}
e = filepath.Walk("/usr/lib", func(path string, info os.FileInfo, err error) error {
if err == nil && libRegEx.MatchString(info.Name()) {
println(info.Name())
}
return nil
})
if e != nil {
log.Fatal(e)
}
Starting with Go 1.16 (Feb 2021), you can use filepath.WalkDir
:从 Go 1.16(2021 年 2 月)开始,您可以使用
filepath.WalkDir
:
package main
import (
"io/fs"
"path/filepath"
)
func walk(s string, d fs.DirEntry, e error) error {
if e != nil { return e }
if ! d.IsDir() {
println(s)
}
return nil
}
func main() {
filepath.WalkDir("..", walk)
}
https://golang.org/pkg/path/filepath#WalkDir https://golang.org/pkg/path/filepath#WalkDir
If you are looking for something that doesn't use walk, I found this project如果您正在寻找不使用步行的东西,我找到了这个项目
The main recursive algorithm seems effective despite using strings.尽管使用了字符串,但主要的递归算法似乎很有效。 It basically amounts to the below code and kinda reminds me of merge sort and other recursive algorithms:
它基本上相当于下面的代码,有点让我想起归并排序和其他递归算法:
func processed(fileName string, processedDirectories []string) bool {
for i := 0; i < len(processedDirectories); i++ {
if processedDirectories[i] != fileName {
continue
}
return true
}
return false
}
func listDirContents(path string, dirs []string) {
files, _ := ioutil.ReadDir(path)
for _, f := range files {
var newPath string
if path != "/" {
newPath = fmt.Sprintf("%s/%s", path, f.Name())
} else {
newPath = fmt.Sprintf("%s%s", path, f.Name())
}
if f.IsDir() {
if !processed(newPath, dirs) {
dirs = append(dirs, newPath)
listDirContents(newPath, dirs)
}
} else {
fmt.Println(newPath)
}
}
}
That actually prints all found paths starting from the provided directory and includes all sub-directories.这实际上会打印从提供的目录开始的所有找到的路径,并包括所有子目录。 Therefor you would have to check if the path contains your target string instead of just printing the path with
fmt.Println()
statements.因此,您必须检查路径是否包含目标字符串,而不仅仅是使用
fmt.Println()
语句打印路径。
After trying it out vs the find
command, it scanned my /home
directory in about .8s... the find
command found the same files but did it in about .3s (a full .5s faster than the above algorithm).在与
find
命令对比后,它在大约 0.8 秒内扫描了我的/home
目录...... find
命令找到了相同的文件,但在大约 0.3 秒内完成(比上述算法快 0.5 秒)。
You can use all the files in the directory using following code:您可以使用以下代码使用目录中的所有文件:
files, err := ioutil.ReadDir(dirPath)
check(err)
for _, file := range files {
fmt.Println(dirPath + file.Name())
}
The code is using the io/ioutil
package to read all the files in the given directory and then looping through them to print there names.代码使用
io/ioutil
包读取给定目录中的所有文件,然后循环遍历它们以打印名称。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.