自己最真实的需求,从大学时期产生的各种文件一直被我存着,重复文件就再所难免。已经存在几款查找重复工具可以满足我的基本需求,但是我的个别需求却无法满足,不得不让我重新造轮子,现在将我实现的小工具分享给大家。
我认为具有如下优点
跨平台(支持 Windows, Linux, Mac)可定制(若你会点编程可轻松扩展你的需求)工具特性
跳过 . 开头目录,但会打印出来这些路径跳过大小为 0 的文件打印后缀为 rar zip iso tar gz 的文件,主要是担心解压后会产生重复文件,提醒你关注一下通过比对文件内容 md5 值判定是否重复,坚信内容相同文件就相同多个相同文件一起打印,相同文件有序打印,整体有序打印,便于查看下载 find repetition
备注 ####point#### 标识开始打印 . 开头目录 ####compress#### 标识开始打印后缀为 rar zip iso tar gz 的文件
使用(均在各系统命令行下执行,在工具执行完成后打开 output.txt 文件查看打印)
Windows windows.exe -path=F:\panshiqu 1>output.txt 2>&1 Linux ./linux -path=/home/panshiqu > output.txt Mac ./mac -path=/home/panshiqu > output.txt提醒 你可在分析打印后大致推测出那两个文件夹可能相同,这里推荐你使用 Beyond Compare 比对两个庞大的文件夹是否相同,记得取消对勾 Session => Session Settings => Comparison => Compare timestamps 用于不比对时间戳
源码
package main import ( "bytes" "crypto/md5" "flag" "fmt" "io" "os" "path/filepath" "sort" "strings" ) var kv map[string][]string var point []string var compress []string var path = flag.String("path", "", "") // FileList 文件列表 func FileList(path string) { if err := filepath.Walk(path, func(path string, info os.FileInfo, err error) error { if info == nil { fmt.Println("info", err) return err } if info.IsDir() { if strings.HasPrefix(info.Name(), ".") { point = append(point, path) return filepath.SkipDir } return nil } if info.Size() == 0 { return nil } lowerName := strings.ToLower(info.Name()) if strings.HasSuffix(lowerName, ".rar") || strings.HasSuffix(lowerName, ".zip") || strings.HasSuffix(lowerName, ".iso") || strings.HasSuffix(lowerName, ".tar") || strings.HasSuffix(lowerName, ".gz") { compress = append(compress, path) } f, err := os.Open(path) if err != nil { fmt.Println("Open", err) return err } defer f.Close() md5hash := md5.New() if _, err := io.Copy(md5hash, f); err != nil { fmt.Println("Copy", err) return err } key := fmt.Sprintf("%x", md5hash.Sum(nil)) kv[key] = append(kv[key], path) return nil }); err != nil { fmt.Println("FileList", err) } } // SortOne 一维排序 type SortOne []string func (s SortOne) Len() int { return len(s) } func (s SortOne) Less(i, j int) bool { return bytes.Compare([]byte(s[i]), []byte(s[j])) < 0 } func (s SortOne) Swap(i, j int) { s[i], s[j] = s[j], s[i] } // SortTwo 二维排序 type SortTwo [][]string func (s SortTwo) Len() int { return len(s) } func (s SortTwo) Less(i, j int) bool { return bytes.Compare([]byte(s[i][0]), []byte(s[j][0])) < 0 } func (s SortTwo) Swap(i, j int) { s[i], s[j] = s[j], s[i] } func main() { flag.Parse() kv = make(map[string][]string) FileList(*path) var tmp [][]string for _, v := range kv { if len(v) == 1 { continue } tmp = append(tmp, v) } for i := 0; i < len(tmp); i++ { sort.Sort(SortOne(tmp[i])) } sort.Sort(SortTwo(tmp)) for _, v := range tmp { for _, vv := range v { fmt.Println(vv) } fmt.Println() } fmt.Println("####point####") for _, v := range point { fmt.Println(v) } fmt.Println("####compress####") for _, v := range compress { fmt.Println(v) } }