func main() { var kind string = "files" var ndirs, nfiles int var paths []string flag.Var(&_fthreshold, "ft", "file sizes <= threshhold will not be considered") flag.Var(&_dthreshold, "dt", "directory sizes <= threshhold will not be considered") //fmt.Printf("dedup\n") hf = aeshash.NewAES(0) flag.Parse() if *pat != "" { re, err := regexp.Compile(*pat) if err != nil { return } patre = re } if *dd != "" { re, err := regexp.Compile(*dd) if err != nil { return } ddre = re } fthreshold = int64(_fthreshold.V) dthreshold = int64(_dthreshold.V) //fmt.Printf("fthreshold=%d\n", fthreshold) //fmt.Printf("dthreshold=%d\n", dthreshold) if *dirf { kind = "dirs" } if len(flag.Args()) != 0 { for _, path := range flag.Args() { fi, err := os.Stat(path) if err != nil || fi == nil { fmt.Printf("fi=%#v, err=%v\n", fi, err) panic("bad") } if fi.Mode()&os.ModeDir == os.ModeDir { ndirs++ } else { nfiles++ } paths = append(paths, path) } } scan(paths, ndirs) if *s { asort() check2(kind, ndirs) } else { check(kind, ndirs) } }
func descend(path string, fis []os.FileInfo, ffp func(path string, fis os.FileInfo, hash uint64, size int64), dfp func(path string, fis os.FileInfo, hash uint64, size int64)) (uint64, int64) { var des func(path string, fis []os.FileInfo) (uint64, int64) des = func(path string, fis []os.FileInfo) (uint64, int64) { var hash uint64 var size, sizes int64 var gh = aeshash.NewAES(0) outer: for _, fi := range fis { //fmt.Printf("descend: enter fi.Name=%q\n", fi.Name()) switch { case fi.Mode()&os.ModeDir == os.ModeDir: //fmt.Printf("descend: dir: path=%q, fi.Name()=%q\n", path, fi.Name()) stats.scannedDirs++ if *dd != "" { b := ddre.MatchString(fi.Name()) if b { //fmt.Printf("descend: skip dir=%q\n", fi.Name()) continue } } for _, name := range ignoreList { if fi.Name() == name { fmt.Printf("descend: skip dir=%q\n", fi.Name()) continue outer } } p := fullName(path, fi) //fmt.Printf("descend: dir=%q\n", p) d, err := os.Open(p) if err != nil { continue } fis, err := d.Readdir(-1) if err != nil || fis == nil { fmt.Printf("descend: can't read %q\n", fullName(path, fi)) continue } d.Close() h, size := des(p, fis) hash = h gh.Write64(hash) sizes += size //fmt.Printf("descend: dir: path=%q, fi.Name()=%q, sizes=%d\n", path, fi.Name(), sizes) stats.matchedDirs++ if dfp != nil { //fmt.Printf("descend: dfp: path=%q, fi.Name()=%q, hash=0x%016x, size=%d\n", path, fi.Name(), hash, size) dfp(path, fi, hash, size) } case fi.Mode()&os.ModeType == 0: stats.scannedFiles++ if fi.Size() > fthreshold && (*pat == "" || (*pat != "" && patre.MatchString(fi.Name()))) { if *fr { hash = readFullHash(path, fi) } else { hash = readPartialHash(path, fi) } gh.Write64(hash) sizes += fi.Size() stats.matchedFiles++ //fmt.Printf("descend: file: path=%q, fi.Name()=%q, hash=0x%016x, size=%d, sizes=%d\n", path, fi.Name(), hash, size, sizes) if ffp != nil { ffp(path, fi, hash, size) } } default: continue } } hashes := gh.Sum64() //fmt.Printf("descend: return dir=%q, hashes=0x%016x, sizes=%d\n", path, hashes, sizes) return hashes, sizes } //fmt.Printf("descend: path=%q\n", path) return des(path, fis) }