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输入大小非常大!