hahaxi 发表于 2021-1-14 21:10

[go语言]磁盘重复文件查找

本帖最后由 hahaxi 于 2021-1-14 21:20 编辑

练手做的小工具

查找本地指定路径下md相同的文件

顺便把图片,视频单独展示出来

主分支使用go levelDB,不需要额外配置数据库,需要使用数据库的可切换到mysql分支

gitee传送门
https://gitee.com/cilidm/duplicate_file


> 开始:
>
>MySQL版本需要修改app/db/mysql下数据库配置,LevelDB版本不需要
>
> 初次执行 go run main.go -n -p /home/src
>
> 再次执行 go run main.go

> -n 执行新任务
> -p 检测路径
>
> 如果不需要检测md 请加上 -md false

> 初次执行会先扫描文件并检查重复文件,这个步骤耗时比较长,执行完后 可以在浏览器 http://localhost:8000 查看

> 没有安装golang环境的,可以在命令行执行二进制文件,首次执行要追加-n -p指令,会在目录下生成views网页文件夹以及static js文件夹。

> runtime文件夹保存日志及levelDB数据文件

> 测试环境 darwin10.15.5

hahaxi 发表于 2021-1-14 21:18

本帖最后由 hahaxi 于 2021-1-14 21:21 编辑

顺便分享个图片转webp的代码

jpg2webp
根据磁盘路径转换图片为webp
使用方式 linux、mac
```
./file_wale_2webp_xxx -s /home/pic -t /home/webp
-s 源地址
-d 目标地址
```

package main

import (
      "bytes"
      "crypto/md5"
      "errors"
      "flag"
      "fmt"
      "image"
      "image/gif"
      "image/jpeg"
      "image/png"
      "io"
      "io/ioutil"
      "log"
      "net/http"
      "os"
      "path"
      "path/filepath"
      "strings"
      "sync/atomic"
      "time"

      "github.com/chai2010/webp"
      "github.com/cilidm/toolbox/logging"
      "golang.org/x/image/bmp"
)

func PathExists(path string) (bool, error) {
      _, err := os.Stat(path)
      if err == nil {
                return true, nil
      }
      if os.IsNotExist(err) {
                os.MkdirAll(path, os.ModePerm)
                return false, nil
      }
      return false, err
}

// 判断字符串是否在数组里
func IsContain(items []string, item string) bool {
      for _, eachItem := range items {
                if eachItem == item {
                        return true
                }
      }
      return false
}

func GetMd5(path string) (string, error) {
      f, err := os.Open(path)
      if err != nil {
                return "", err
      }
      defer f.Close()
      md5hash := md5.New()
      if _, err := io.Copy(md5hash, f); err != nil {
                return "", err
      }
      return fmt.Sprintf("%x", md5hash.Sum(nil)), nil
}

func walkDir(dir, dst string) {
      PathExists(dst)
      var num uint64 = 1
      filepath.Walk(dir, func(p string, info os.FileInfo, err error) error {
                if info.IsDir() == false {
                        ext := path.Ext(info.Name())
                        if IsContain([]string{".jpg", ".jpeg", ".png", ".bmp", ".gif"}, ext) {
                              maxChan <- struct{}{}
                              atomic.AddUint64(&num, 1)
                              md, err := GetMd5(p)
                              if err != nil {
                                        logging.Error(err.Error())
                                        return nil
                              }
                              webpFile := dst + "/" + md + ".webp"
                              if CheckFileIsExist(webpFile) == false {
                                        go change2webp(p, webpFile, 90, true)
                              }
                        }
                }
                return nil
      })
      close(maxChan)
      searchDone <- struct{}{}
}

/**
* 判断文件是否存在存在返回 true 不存在返回false
*/
func CheckFileIsExist(filename string) bool {
      var exist = true
      if _, err := os.Stat(filename); os.IsNotExist(err) {
                exist = false
      }
      return exist
}

func change2webp(p1, p2 string, quality float32, Log bool) {
      fmt.Println("begin", p1)
      err := WebpEncoder(p1, p2, quality, Log)
      if err != nil {
                logging.Error(err.Error())
      }
      <-maxChan
}

func WebpEncoder(p1, p2 string, quality float32, Log bool) (err error) {
      logging.Debug("img path :", path.Base(p1), ",quality is :", quality)
      var buf bytes.Buffer
      var img image.Image
      data, err := ioutil.ReadFile(p1)
      if err != nil {
                return err
      }
      contentType := GetFileContentType(data[:512])
      if strings.Contains(contentType, "jpeg") {
                img, _ = jpeg.Decode(bytes.NewReader(data))
      } else if strings.Contains(contentType, "png") {
                img, _ = png.Decode(bytes.NewReader(data))
      } else if strings.Contains(contentType, "bmp") {
                img, _ = bmp.Decode(bytes.NewReader(data))
      } else if strings.Contains(contentType, "gif") {
                logging.Warn("Gif support is not perfect!")
                img, _ = gif.Decode(bytes.NewReader(data))
      }
      if img == nil {
                msg := "image file " + path.Base(p1) + " is corrupted or not supported"
                err = errors.New(msg)
                return err
      }
      if err = webp.Encode(&buf, img, &webp.Options{Lossless: false, Quality: quality}); err != nil {
                return err
      }
      if err = ioutil.WriteFile(p2, buf.Bytes(), 0644); err != nil {
                return err
      }
      if Log {
                logging.Info("Save to " + p2 + " ok!")
      }
      return nil
}

func GetFileContentType(buffer []byte) string {
      contentType := http.DetectContentType(buffer)
      return contentType
}

var (
      maxChan    = make(chan struct{}, 10)
      done       = make(chan bool)
      searchDone = make(chan struct{})
      source   string
      dst      string
)

func monitorDone() {
      select {
      case <-searchDone:
                for {
                        if len(maxChan) == 0 {
                              done <- true
                              break
                        }
                }
      }
}

func init() {
      go monitorDone()
      flag.StringVar(&source, "s", "", "源地址")
      flag.StringVar(&dst, "d", "", "目标地址")
      flag.Parse()
}

func main() {
      if source == "" || dst == "" {
                log.Fatal("请输入源地址及目标地址")
      }

      start := time.Now()

      walkDir(source, dst)

      select {
      case <-done:
                fmt.Println("文件更新完毕,耗时", time.Since(start))
      }
}

页: [1]
查看完整版本: [go语言]磁盘重复文件查找