Golang磁盘空间分析工具 - Tdu Top Disk Usage v1.34 使用指南

Golang磁盘空间分析工具 - Tdu Top Disk Usage v1.34 使用指南 你想知道是什么占用了你所有的磁盘空间吗?

这个用Go编写的命令行工具,可以估算给定路径下所有文件占用的磁盘空间。它会显示一个按大小排序的最大项目列表。其估算方法类似于GNU Coreutils包中的 du -skx 命令。

主要特性:

  • 纯Go编写的单一原生二进制文件,无外部依赖
  • 轻松查找最大的文件和目录
  • 显示包含百分比和总计的摘要
  • 显示分区信息(大小、inode、文件系统等)
  • 统计所有类型的文件:套接字、符号链接、硬链接…
  • 将结果导出为NCDU的JSON格式

自版本1.32以来的新功能:

  • 在TTY终端上使用彩色显示扫描进度
  • 添加对FreeBSD 11的支持
  • 添加对树莓派的支持
  • 添加对在非交互模式(无TTY)下通过SSH运行的支持
  • 添加PDF格式的手册
  • 检测输出是否被重定向到文件
  • [Windows] 最大化控制台窗口

完整更新日志:https://bitbucket.org/josephpaul0/tdu/src/master/Changelog

适用于Linux(包括树莓派)、FreeBSD和Windows的即用型软件包位于: https://bitbucket.org/josephpaul0/tdu/downloads/ 源代码:https://bitbucket.org/josephpaul0/tdu

欢迎发送您的反馈和建议!


更多关于Golang磁盘空间分析工具 - Tdu Top Disk Usage v1.34 使用指南的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang磁盘空间分析工具 - Tdu Top Disk Usage v1.34 使用指南的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


这是一个非常实用的磁盘空间分析工具。Tdu(Top Disk Usage)在Go社区中因其高效和跨平台特性而备受青睐。以下是对其核心功能和使用方法的专业解析:

核心实现原理

Tdu通过并发遍历文件系统来统计磁盘使用情况,其算法优化了大规模目录扫描的性能。以下是类似功能的简化实现示例:

package main

import (
    "fmt"
    "io/fs"
    "os"
    "path/filepath"
    "sync"
)

type FileInfo struct {
    Path string
    Size int64
}

func scanDir(root string, results chan<- FileInfo, wg *sync.WaitGroup) {
    defer wg.Done()
    
    filepath.WalkDir(root, func(path string, d fs.DirEntry, err error) error {
        if err != nil {
            return nil
        }
        
        info, err := d.Info()
        if err != nil {
            return nil
        }
        
        if !d.IsDir() {
            results <- FileInfo{
                Path: path,
                Size: info.Size(),
            }
        }
        
        return nil
    })
}

func main() {
    results := make(chan FileInfo, 100)
    var wg sync.WaitGroup
    
    wg.Add(1)
    go scanDir("/path/to/scan", results, &wg)
    
    go func() {
        wg.Wait()
        close(results)
    }()
    
    var totalSize int64
    for file := range results {
        totalSize += file.Size
        fmt.Printf("%s: %d bytes\n", file.Path, file.Size)
    }
    
    fmt.Printf("Total size: %d bytes\n", totalSize)
}

关键特性实现分析

  1. 并发文件统计
func collectSizes(paths []string) map[string]int64 {
    sizeMap := make(map[string]int64)
    var mu sync.Mutex
    var wg sync.WaitGroup
    
    for _, path := range paths {
        wg.Add(1)
        go func(p string) {
            defer wg.Done()
            size := getFileSize(p)
            
            mu.Lock()
            sizeMap[p] = size
            mu.Unlock()
        }(path)
    }
    
    wg.Wait()
    return sizeMap
}
  1. NCDU JSON格式导出
type NCDUOutput struct {
    Version   int          `json:"version"`
    Timestamp int64        `json:"timestamp"`
    Data      []NCDUEntry  `json:"data"`
}

type NCDUEntry struct {
    Name     string      `json:"name"`
    Size     int64       `json:"dsize"`
    DiskSize int64       `json:"asize"`
    Inode    uint64      `json:"ino,omitempty"`
}

func exportToNCDU(entries []FileInfo) NCDUOutput {
    output := NCDUOutput{
        Version:   1,
        Timestamp: time.Now().Unix(),
        Data:      make([]NCDUEntry, len(entries)),
    }
    
    for i, entry := range entries {
        output.Data[i] = NCDUEntry{
            Name:     filepath.Base(entry.Path),
            Size:     entry.Size,
            DiskSize: calculateDiskUsage(entry.Path),
        }
    }
    
    return output
}

平台特定实现

对于Windows系统的控制台最大化功能:

// +build windows
package main

import (
    "syscall"
)

func maximizeConsole() {
    kernel32 := syscall.NewLazyDLL("kernel32.dll")
    getConsoleWindow := kernel32.NewProc("GetConsoleWindow")
    showWindow := syscall.NewLazyDLL("user32.dll").NewProc("ShowWindow")
    
    hWnd, _, _ := getConsoleWindow.Call()
    if hWnd != 0 {
        showWindow.Call(hWnd, 3) // SW_MAXIMIZE = 3
    }
}

性能优化技巧

Tdu在扫描大目录时使用的内存优化策略:

type Scanner struct {
    bufferPool sync.Pool
    semaphore  chan struct{}
}

func (s *Scanner) scanWithLimit(root string, maxConcurrent int) {
    s.semaphore = make(chan struct{}, maxConcurrent)
    
    var traverse func(string)
    traverse = func(path string) {
        s.semaphore <- struct{}{}
        defer func() { <-s.semaphore }()
        
        entries, _ := os.ReadDir(path)
        for _, entry := range entries {
            fullPath := filepath.Join(path, entry.Name())
            if entry.IsDir() {
                go traverse(fullPath)
            } else {
                s.processFile(fullPath)
            }
        }
    }
    
    traverse(root)
}

这个工具展示了Go在系统工具开发中的优势:静态编译、跨平台支持和高效的并发处理。其实现方式为开发类似磁盘分析工具提供了很好的参考。

回到顶部