以递归方式查找目录中的文件

时间:2017-11-13 14:23:01

标签: file search recursion go

我希望递归地找到与目录中特定模式匹配的所有文件(包括子目录)。我写了代码来做到这一点:

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())
    }
}

不幸的是,它只在/usr/bin中搜索,但我也想在其子目录中搜索匹配项。我怎样才能做到这一点?感谢。

4 个答案:

答案 0 :(得分:7)

标准库的filepath软件包包括Walk用于此目的:"遍历以root为根的文件树,为树中的每个文件或目录调用walkFn ,包括root。"例如:

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(f.Name())
    }
    return nil
})
if e != nil {
    log.Fatal(e)
}

答案 1 :(得分:6)

从 Go 1.16(2021 年 2 月)开始,您可以使用 private CSVParser openCsv() throws IOException { final var csvFormat = CSVFormat.DEFAULT .withFirstRecordAsHeader() .withDelimiter(detectDelimiter()) .withTrim(); return new CSVParser(new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8), csvFormat); }

filepath.WalkDir

https://golang.org/pkg/path/filepath#WalkDir

答案 2 :(得分:0)

如果您正在寻找不需要步行的东西,我发现this project

尽管使用了字符串,但主要的递归算法似乎仍然有效。它基本上等于以下代码,有点让我想起了合并排序和其他递归算法:

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)
        }
    }
}

这实际上会打印从提供的目录开始的所有找到的路径,并包括所有子目录。因此,您必须检查路径是否包含目标字符串,而不是仅使用fmt.Println()语句打印路径。

在尝试使用find命令后,它在大约0.8秒内扫描了我的/home目录... find命令找到了相同的文件,但在大约0.3秒内完成了扫描(比上述算法快0.5秒)。

答案 3 :(得分:-2)

您可以使用以下代码使用目录中的所有文件:

files, err := ioutil.ReadDir(dirPath)
check(err)

for _, file := range files {
    fmt.Println(dirPath + file.Name())
}

代码使用io/ioutil包读取给定目录中的所有文件,然后循环遍历它们以在其中打印名称。