163 lines
2.8 KiB
Go
163 lines
2.8 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"sort"
|
|
"sync"
|
|
)
|
|
|
|
var (
|
|
config Config
|
|
count int64
|
|
)
|
|
|
|
func printExts(exts []Ext) {
|
|
sort.Slice(exts, func(i, j int) bool {
|
|
return exts[i].size > exts[j].size
|
|
})
|
|
|
|
top := 0
|
|
fmt.Printf("\nExtensions:\n\n")
|
|
for _, ext := range exts {
|
|
fmt.Printf("%s %s\n", alignRight(6, sizeConv(ext.size)), ext.ext)
|
|
top++
|
|
if top >= config.top {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
func printNointer(d Dir) {
|
|
var exts []Ext
|
|
top := 0
|
|
|
|
items := sortItems(recurse(d))
|
|
|
|
fmt.Printf("\nDirectories:\n\n")
|
|
for i, item := range items {
|
|
if item.isDir {
|
|
if i+1 < len(items) && items[i+1].isDir && isSubfolder(item.dir.path, items[i+1].dir.path) {
|
|
item.dir.size -= items[i+1].dir.size
|
|
items = sortItems(items)
|
|
continue
|
|
}
|
|
fmt.Printf("%s %s\n", alignRight(6, sizeConv(item.dir.size)), item.dir.path)
|
|
top++
|
|
}
|
|
if top >= config.top {
|
|
break
|
|
}
|
|
}
|
|
|
|
top = 0
|
|
fmt.Printf("\nFiles:\n\n")
|
|
for _, item := range items {
|
|
if !item.isDir {
|
|
if top < config.top {
|
|
fmt.Printf("%s %s\n", alignRight(6, sizeConv(item.file.size)), item.file.name)
|
|
top++
|
|
}
|
|
exts = getExts(exts, item.file.name, item.file.size)
|
|
}
|
|
}
|
|
|
|
printExts(exts)
|
|
|
|
total := items[0].dir.size
|
|
fmt.Printf("\nTotal: %s (%d items)\n", sizeConv(total), count)
|
|
}
|
|
|
|
func scan(dir string, wg *sync.WaitGroup, mu *sync.Mutex) Dir {
|
|
var d Dir
|
|
d.path = dir
|
|
|
|
files, err := os.ReadDir(dir)
|
|
if err != nil {
|
|
printerr(err)
|
|
return d
|
|
}
|
|
|
|
var localWg sync.WaitGroup
|
|
|
|
for _, file := range files {
|
|
if config.vverbose {
|
|
fmt.Println(filepath.Join(dir, file.Name()))
|
|
}
|
|
if exclude(filepath.Join(dir, file.Name())) {
|
|
continue
|
|
}
|
|
if file.IsDir() {
|
|
if config.fsOnly && !fsOnly(filepath.Join(dir, file.Name())) {
|
|
continue
|
|
}
|
|
localWg.Add(1)
|
|
go func(fileName string) {
|
|
defer localWg.Done()
|
|
subDir := scan(filepath.Join(dir, fileName), &localWg, mu)
|
|
mu.Lock()
|
|
if subDir.size > config.dmin {
|
|
d.dirs = append(d.dirs, subDir)
|
|
}
|
|
d.size += subDir.size
|
|
mu.Unlock()
|
|
}(file.Name())
|
|
} else {
|
|
localWg.Add(1)
|
|
go func(fileName string) {
|
|
defer localWg.Done()
|
|
var f File
|
|
f.size = getSize(filepath.Join(dir, file.Name()))
|
|
mu.Lock()
|
|
d.size += f.size
|
|
f.name = file.Name()
|
|
f.prev = &d
|
|
d.files = append(d.files, f)
|
|
mu.Unlock()
|
|
}(file.Name())
|
|
}
|
|
count += 1
|
|
localWg.Wait()
|
|
}
|
|
return d
|
|
}
|
|
|
|
func main() {
|
|
var wg sync.WaitGroup
|
|
var mu sync.Mutex
|
|
|
|
runtime.GOMAXPROCS(config.threads)
|
|
|
|
parseArgs()
|
|
if config.verbose {
|
|
printConfig()
|
|
}
|
|
|
|
if !config.silent {
|
|
fmt.Printf("Scanning %s...\n", config.dir)
|
|
}
|
|
|
|
getDirMount(config.dir)
|
|
|
|
d := scan(config.dir, &wg, &mu)
|
|
wg.Wait()
|
|
|
|
if !config.silent {
|
|
fmt.Printf("\nScanned %d items\n", count)
|
|
}
|
|
if config.verbose {
|
|
fmt.Println("Sorting...")
|
|
}
|
|
|
|
if !config.noninter {
|
|
show(d)
|
|
}
|
|
|
|
if !config.silent {
|
|
printNointer(d)
|
|
}
|
|
os.Exit(0)
|
|
}
|