跨平台可定制查找重复文件工具
2016-11-30 15:27:48
自己最真实的需求,从大学时期产生的各种文件一直被我存着,重复文件就再所难免。已经存在几款查找重复工具可以满足我的基本需求,但是我的个别需求却无法满足,不得不让我重新造轮子,现在将我实现的小工具分享给大家。
我认为具有如下优点
- 跨平台(支持 Windows, Linux, Mac)
- 可定制(若你会点编程可轻松扩展你的需求)
工具特性
- 跳过
.
开头目录,但会打印出来这些路径 - 跳过大小为
0
的文件 - 打印后缀为
rar zip iso tar gz
的文件,主要是担心解压后会产生重复文件,提醒你关注一下 - 通过比对文件内容
md5
值判定是否重复,坚信内容相同文件就相同 - 多个相同文件一起打印,相同文件有序打印,整体有序打印,便于查看
备注
####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
比对两个庞大的文件夹是否相同,记得 会话 => 会话设置 => 比较
取消比较时间戳,勾选比较内容
源码
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)
}
}