GoHash.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. package main
  2. import (
  3. "crypto/sha256"
  4. "encoding/hex"
  5. "encoding/json"
  6. "flag"
  7. "fmt"
  8. "io"
  9. "io/ioutil"
  10. "log"
  11. "os"
  12. "path/filepath"
  13. "runtime"
  14. "sync"
  15. )
  16. type Fdhashes struct {
  17. Path string
  18. Hashes map[string]string
  19. }
  20. var hashes map[string]Fdhashes
  21. var wg sync.WaitGroup
  22. var mu sync.RWMutex
  23. func main() {
  24. runtime.GOMAXPROCS(5)
  25. hashes = make(map[string]Fdhashes)
  26. flag.Parse()
  27. myFile := flag.Arg(0)
  28. file, err := os.Stat(myFile)
  29. if os.IsNotExist(err) {
  30. log.Fatalln("File does not exists:", myFile)
  31. }
  32. if file.IsDir() {
  33. log.Println("start with folder:", myFile)
  34. processFolder(myFile)
  35. } else {
  36. log.Printf("file %s has hash %s\n", myFile, getHash(myFile))
  37. }
  38. fmt.Println("waiting")
  39. wg.Wait()
  40. log.Println("done")
  41. }
  42. func getHash(fileStr string) string {
  43. f, err := os.Open(fileStr)
  44. if err != nil {
  45. log.Fatal(err)
  46. }
  47. defer f.Close()
  48. h := sha256.New()
  49. if _, err := io.Copy(h, f); err != nil {
  50. log.Fatal(err)
  51. }
  52. return hex.EncodeToString(h.Sum(nil))
  53. }
  54. func outputHash(fileStr string) {
  55. var hashFile Fdhashes
  56. doHash := true
  57. defer wg.Done()
  58. fmt.Print(".")
  59. dir, fileName := filepath.Split(fileStr)
  60. if fileName == ".fdhashes3" {
  61. return
  62. }
  63. mu.Lock()
  64. hashFile, ok := hashes[dir]
  65. if !ok {
  66. _, err := os.Stat(dir + ".fdhashes3")
  67. if os.IsNotExist(err) {
  68. hashFile = Fdhashes{Path: dir, Hashes: make(map[string]string)}
  69. } else {
  70. hashFile = loadHashfile(dir + ".fdhashes3")
  71. }
  72. hashes[dir] = hashFile
  73. saveHashfile(hashFile)
  74. }
  75. _, ok = hashFile.Hashes[fileName]
  76. doHash = !ok
  77. hashFile = hashes[dir]
  78. mu.Unlock()
  79. if doHash {
  80. hash := getHash(fileStr)
  81. mu.Lock()
  82. hashFile.Hashes[fileName] = hash
  83. saveHashfile(hashFile)
  84. mu.Unlock()
  85. log.Printf("file %s has hash %s\n", fileStr, hash)
  86. }
  87. }
  88. func processFolder(folder string) {
  89. err := filepath.Walk(folder, func(path string, info os.FileInfo, err error) error {
  90. if !info.IsDir() {
  91. wg.Add(1)
  92. go outputHash(path)
  93. }
  94. return nil
  95. })
  96. if err != nil {
  97. panic(err)
  98. }
  99. }
  100. func saveHashfile(hashFile Fdhashes) {
  101. b, err := json.Marshal(hashFile)
  102. if err != nil {
  103. fmt.Println(err)
  104. return
  105. }
  106. err = ioutil.WriteFile(hashFile.Path+".fdhashes3", b, 0644)
  107. if err != nil {
  108. panic(err)
  109. }
  110. }
  111. func loadHashfile(filename string) Fdhashes {
  112. file, err := ioutil.ReadFile(filename)
  113. if err != nil {
  114. panic(err)
  115. }
  116. data := Fdhashes{}
  117. err = json.Unmarshal([]byte(file), &data)
  118. if err != nil {
  119. panic(err)
  120. }
  121. return data
  122. }