File 在目录中查找重复的文件

File 在目录中查找重复的文件,file,go,File,Go,这是我的第一个围棋项目。我正在学习这门语言,但是理解所有的概念有点困难,所以为了练习,我写了一个代码来检测同一个文件。这是一个简单的程序,递归地检查目录中的重复文件 但是: 如何检测目录文件中的重复文件 问题不是递归的。问题是如何比较您可以获取每个文件体的哈希值,然后比较字典/映射中的哈希值 package main import ( "crypto/md5" "fmt" "io" "io/ioutil" "log" "os" ) func m

这是我的第一个围棋项目。我正在学习这门语言,但是理解所有的概念有点困难,所以为了练习,我写了一个代码来检测同一个文件。这是一个简单的程序,递归地检查目录中的重复文件

但是:

如何检测目录文件中的重复文件


问题不是递归的。问题是如何比较

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

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
}

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

}
主程序包
进口(
“加密/sha256”
“编码/十六进制”
“fmt”
“操作系统”
“路径/文件路径”
“同步”
“旗帜”
“运行时”
“io”
)
var-dir字符串
var工人国际
类型结果结构{
文件字符串
sha256[32]字节
}

func工人(输入chan string,results chanNever used go,它是否有哈希映射/集合/字典数据结构?您可以将文件名插入结构中。由于这些结构只允许唯一值,您可以假设如果结构的大小没有改变,它一定是重复的。在任何语言中,概念都是相同的,您遇到了什么问题你特别喜欢Go?为什么md5?md5对所有文件都有影响?你不太可能与标准库中的任何哈希算法发生哈希冲突。它们都可以接受非常大的输入大小。坦克,明白!sha256输入大小非常大!