Golang代码搜集-访Unix du命令的目录文件数量和文件总大小统计程序

本文介绍了一个使用Go语言编写的简单Unix du命令程序,该程序能够统计指定目录下的文件数量及总大小。通过控制并发数量、使用信号量、定时器等功能,实现了高效的目录遍历。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这段代码出自《Go程序设计语言》(英文版)第247页,简单的访Unix du命令程序,用于统计某目录的文件数量和总大小,代码演示了如何控制并发数量、输入命令、定时器等。

package main

import (
    "os"
    "io/ioutil"
    "fmt"
    "path/filepath"
    "time"
    "flag"
    "sync"
)

func walkDir(dir string,wg *sync.WaitGroup, fileSizes chan<- int64) {
    //一个goroutine结束 -1
    defer wg.Done()
    //获取目录下的文件和文件夹列表
    for _, entry := range dirents(dir) {
        if entry.IsDir() {
            //每启动一个新goroutine则 +1
            wg.Add(1)
            //拼接子目录路径
            subdir := filepath.Join(dir, entry.Name())
            //递归子目录
            go walkDir(subdir, wg,fileSizes)
        } else {
            //如果是文件,则累加文件大小
            fileSizes <- entry.Size()
        }
    }
}
// sema是限制dirents并发数量的信号量
var sema = make(chan struct{}, 20)
//获取某目录下的文件和文件夹列表
func dirents(dir string) []os.FileInfo {
    sema <- struct{}{} // acquire token
    defer func() { <-sema }() // release token
    entries, err := ioutil.ReadDir(dir)
    if err != nil {
        fmt.Fprintf(os.Stderr, "du1:%v\n", err)
        return nil
    }
    return entries
}
//输入参数是否包括 -v
var verbose = flag.Bool("v", false, "show verbose progress messages")
func main() {
    //读取输入参数
    flag.Parse()
    roots := flag.Args()
    if len(roots) == 0 {
        roots = []string{"."}
    }
    //记录搜索开始时间
    start := time.Now()
    //goroutine计数
    var wg sync.WaitGroup
    fsizes := make(chan int64)
    for _, root := range roots {
        //每启动一个新goroutine则 +1
        wg.Add(1)
        go  walkDir(root,&wg, fsizes)
    }
    go func(){
        //等待所有goroutine结束后关闭fsizes
        wg.Wait()
        close(fsizes)
    }()
    //声明变量保存 文件总数量和总大小
    var nfiles, nbytes int64
    //声明定时器,500ms
    var tick <-chan time.Time
    //输入参数包括 -v,则启用定时器
    if *verbose{
        tick = time.Tick(500 * time.Millisecond)
    }
loop:
    for {
        select {
        case size, ok := <-fsizes:
            //当fsizes关闭后,跳出for循环
            if !ok {
                break loop
            }
            //fsizes有数据,则累加文件数量和总大小
            nfiles ++
            nbytes += size
        case <-tick:
            //定时显示当前进度
            printDiskUsage(nfiles, nbytes)
        }
    }
    //显示最终结果
    printDiskUsage(nfiles, nbytes)
    fmt.Printf("%v", time.Since(start))
}
func printDiskUsage(nfiles, nbytes int64) {
    fmt.Printf("%d files %.1f GB\n", nfiles, float64(nbytes)/1e9)
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值