首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在GOLANG中尽可能快地递归地遍历所有文件夹中的所有文件。

在GOLANG中尽可能快地递归地遍历所有文件夹中的所有文件。
EN

Stack Overflow用户
提问于 2022-04-06 12:32:49
回答 1查看 1.3K关注 0票数 1

我正面临着一个问题,即使在论坛上度过了一天,我仍然不能完全理解和解决。

在这里,我创建了一个函数,它循环遍历所有的文件夹以及它的子文件夹,它有两个子函数:-对于找到的每个文件,列出文件的名称。-对于找到的每个文件夹,重新启动相同的父函数以再次查找子文件和文件夹。

为了简单起见,宏列出了具有递归的树中的所有文件。但我的目标是尽快做到这一点,所以每当我遇到一个新文件夹时,我都会运行一个新的大猩猩。

问题:

我的问题是当树结构太大时(文件夹和子文件夹中的文件夹太多.)脚本生成了太多的线程,因此给出了一个错误。所以我增加了这个限制,但是突然之间,pc不再想要了

因此,我的问题是,如何使一个符合我的代码的工作系统(具有池大小)?不管我看了多少,我都不知道该怎么说,例如,如何生成新的大猩猩,直到一定的限度,空出缓冲区的时间。

源代码:

https://github.com/LaM0uette/FilesDIR/tree/V0.5

主要:

代码语言:javascript
运行
复制
package main

import (
    "FilesDIR/globals"
    "FilesDIR/task"
    "fmt"
    "log"
    "runtime/debug"
    "sync"
    "time"
)

func main() {
    timeStart := time.Now()
    debug.SetMaxThreads(5 * 1000)

    var wg sync.WaitGroup

    // task.DrawStart()

    /*
        err := task.LoopDir(globals.SrcPath)
        if err != nil {
            log.Print(err.Error())
        }
    */

    err := task.LoopDirsFiles(globals.SrcPath, &wg) // globals.SrcPath = My path with ~2000000 files ( this is a serveur of my entreprise)
    if err != nil {
        log.Print(err.Error())
    }

    wg.Wait()

    fmt.Println("FINI: Nb Fichiers: ", task.Id)

    timeEnd := time.Since(timeStart)
    fmt.Println(timeEnd)
}

任务:

代码语言:javascript
运行
复制
package task

import (
    "fmt"
    "io/ioutil"
    "log"
    "os"
    "path/filepath"
    "strings"
    "sync"
    "time"
)

var Id = 0

// LoopDir TODO: Code à supprimer / Code to delete
func LoopDir(path string) error {
    var wg sync.WaitGroup

    countDir := 0

    err := filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
        if err != nil {
            return err
        }

        if info.IsDir() {
            wg.Add(1)
            countDir++

            go func() {
                err := loopFiles(path, &wg)
                if err != nil {
                    log.Println(err.Error())
                }
            }()
        }

        return nil
    })
    if err != nil {
        return err
    }

    wg.Wait()
    fmt.Println("Finished", countDir, Id)
    return nil
}

// loopFiles TODO: Code à supprimer / Code to delete
func loopFiles(path string, wg *sync.WaitGroup) error {

    files, err := ioutil.ReadDir(path)
    if err != nil {
        wg.Done()
        return err
    }

    for _, file := range files {
        if !file.IsDir() {
            go fmt.Println(file.Name())
            Id++
        }
    }

    wg.Done()
    return nil
}

func LoopDirsFiles(path string, wg *sync.WaitGroup) error {
    wg.Add(1)
    defer wg.Done()

    files, err := ioutil.ReadDir(path)
    if err != nil {
        return err
    }

    for _, file := range files {
        if !file.IsDir() && !strings.Contains(file.Name(), "~") {
            fmt.Println(file.Name(), Id)
            Id++
        } else if file.IsDir() {
            go func() {
                err = LoopDirsFiles(filepath.Join(path, file.Name()), wg)
                if err != nil {
                    log.Print(err)
                }
            }()
            time.Sleep(20 * time.Millisecond)
        }
    }
    return nil
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-04-06 14:13:53

如果您不想使用任何外部包,您可以为文件处理创建一个单独的工作例程,然后开始您想要的工作人员。然后,在主线程中递归地进入树,并将作业发送给工人。如果任何员工“有时间”,它将从作业通道获取以下作业并处理它。

代码语言:javascript
运行
复制
var (
    wg   *sync.WaitGroup
    jobs chan string = make(chan string)
)

func loopFilesWorker() error {
    for path := range jobs {
        files, err := ioutil.ReadDir(path)
        if err != nil {
            wg.Done()
            return err
        }

        for _, file := range files {
            if !file.IsDir() {
                fmt.Println(file.Name())
            }
        }
        wg.Done()
    }
    return nil
}

func LoopDirsFiles(path string) error {
    files, err := ioutil.ReadDir(path)
    if err != nil {
        return err
    }
    //Add this path as a job to the workers
    //You must call it in a go routine, since if every worker is busy, then you have to wait for the channel to be free.
    go func() {
        wg.Add(1)
        jobs <- path
    }()
    for _, file := range files {
        if file.IsDir() {
            //Recursively go further in the tree
            LoopDirsFiles(filepath.Join(path, file.Name()))
        }
    }
    return nil
}

func main() {
    //Start as many workers you want, now 10 workers
    for w := 1; w <= 10; w++ {
        go loopFilesWorker()
    }
    //Start the recursion
    LoopDirsFiles(globals.SrcPath)
    wg.Wait()
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71766816

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档