为了账号安全,请及时绑定邮箱和手机立即绑定

查找目录中的重复文件

查找目录中的重复文件

Go
阿波罗的战车 2023-04-17 16:31:26
这是我的第一个 Go 程序。我正在学习这门语言,但理解所有概念有点困难,所以为了练习我写了一个代码来检测相同的文件。这是一个简单的程序,可以递归地检查目录中的重复文件。但:如何检测目录文件中的重复文件问题不是递归目录。问题是如何比较
查看完整描述

2 回答

?
繁花如伊

TA贡献2012条经验 获得超12个赞

您可以获取每个文件主体的哈希值,然后比较字典/映射中的哈希值。


package main


import (

    "crypto/md5"

    "fmt"

    "io"

    "io/ioutil"

    "log"

    "os"

)


func main() {

    contentHashes := make(map[string]string)

    if err := readDir("./", contentHashes); err != nil {

        log.Fatal(err)

    }

}


func readDir(dirName string, contentHashes map[string]string) (err error) {

    filesInfos, err := ioutil.ReadDir(dirName)

    if err != nil {

        return

    }

    for _, fi := range filesInfos {

        if fi.IsDir() {

            err := readDir(dirName+fi.Name()+"/", contentHashes)

            if err != nil {

                return err

            }

        } else {

            // The important bits for this question

            location := dirName + fi.Name()

            // open the file

            f, err := os.Open(location)

            if err != nil {

                return err

            }

            h := md5.New()

            // copy the file body into the hash function

            if _, err := io.Copy(h, f); err != nil {

                return err

            }

            // Check if a file body with the same hash already exists

            key := fmt.Sprintf("%x", h.Sum(nil))

            if val, exists := contentHashes[key]; exists {

                fmt.Println("Duplicate found", val, location)

            } else {

                contentHashes[key] = location

            }

        }

    }

    return

}


查看完整回答
反对 回复 2023-04-17
?
肥皂起泡泡

TA贡献1829条经验 获得超6个赞

使用 sha256 比较文件


例子:


package main


import (

    "crypto/sha256"

    "encoding/hex"

    "fmt"

    "os"

    "path/filepath"

    "sync"

    "flag"

    "runtime"

    "io"

)


var dir string

var workers int


type Result struct {

    file   string

    sha256 [32]byte

}


func worker(input chan string, results chan<- *Result, wg *sync.WaitGroup) {

    for file := range input {

        var h = sha256.New()

        var sum [32]byte

        f, err := os.Open(file)

        if err != nil {

            fmt.Fprintln(os.Stderr, err)

            continue

        }

        if _, err = io.Copy(h, f); err != nil {

            fmt.Fprintln(os.Stderr, err)

            f.Close()

            continue

        }

        f.Close()

        copy(sum[:], h.Sum(nil))

        results <- &Result{

            file:   file,

            sha256: sum,

        }

    }

    wg.Done()

}


func search(input chan string) {

    filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {

        if err != nil {

            fmt.Fprintln(os.Stderr, err)

        } else if info.Mode().IsRegular() {

            input <- path

        }

        return nil

    })

    close(input)

}


func main() {


    flag.StringVar(&dir, "dir", ".", "directory to search")

    flag.IntVar(&workers, "workers", runtime.NumCPU(), "number of workers")

    flag.Parse()


    fmt.Printf("Searching in %s using %d workers...\n", dir, workers)


    input := make(chan string)

    results := make(chan *Result)


    wg := sync.WaitGroup{}

    wg.Add(workers)


    for i := 0; i < workers; i++ {

        go worker(input, results, &wg)

    }


    go search(input)

    go func() {

        wg.Wait()

        close(results)

    }()


    counter := make(map[[32]byte][]string)

    for result := range results {

        counter[result.sha256] = append(counter[result.sha256], result.file)

    }


    for sha, files := range counter {

        if len(files) > 1 {

            fmt.Printf("Found %d duplicates for %s: \n", len(files), hex.EncodeToString(sha[:]))

            for _, f := range files {

                fmt.Println("-> ", f)

            }

        }

    }


}


查看完整回答
反对 回复 2023-04-17
  • 2 回答
  • 0 关注
  • 113 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信