提问人:siwm 提问时间:7/18/2023 最后编辑:siwm 更新时间:7/18/2023 访问量:258
使用 Golang 获取目录磁盘使用情况
Get Directory Disk Usage with Golang
问:
我尝试使用 golang 学习目录的磁盘用法,但下面的应用程序计算不正确。我不想使用 .我尝试过,但没有得到实际的目录大小。我在下面分享了相关的代码语句,正确的目录信息和应用程序的结果。filepath.Walk
os.Stat()
const (
B = 1
KB = 1024 * B
MB = 1024 * KB
GB = 1024 * MB
)
type DiskStatus struct {
All uint64
Free uint64
Used uint64
}
func DiskUsage(path string) (ds DiskStatus) {
fs := syscall.Statfs_t{}
err := syscall.Statfs(path, &fs)
if err != nil {
return
}
ds.All = fs.Blocks * uint64(fs.Bsize)
ds.Free = fs.Bfree * uint64(fs.Bsize)
ds.Used = ds.All - ds.Free
fmt.Println(path, ds.Used)
return ds
}
func GetDir(destination_directory string) *[]model.Directory {
var dir []model.Directory
items, err := ioutil.ReadDir(destination_directory)
if err != nil {
log.Fatalln(err)
}
for _, item := range items {
size := DiskUsage(destination_directory+item.Name()).Used / GB
item := model.Directory{Path: item.Name(), TotalSize: size}
dir = append(dir, item)
}
return &dir
}
正确的目录信息:
$du -sh *
8.0K containers
2.0G testfolder
3.2M workspace
按应用划分的结果:
containers --> 90
testfolder --> 90
workspace --> 90
答:
4赞
VonC
7/18/2023
#1
我相信你滥用了系统调用。Statfs
函数:它返回文件系统统计信息,而不是单个目录或文件的大小。因此,您看到的输出不是单个目录的大小,而是这些目录所在的文件系统的整体磁盘使用情况。
如果您不想使用 filepath.Walk
(这实际上是通过递归遍历所有文件来计算目录大小的好方法),您可以编写自己的递归函数。
package main
import (
"os"
"log"
"fmt"
)
const (
B = 1
KB = 1024 * B
MB = 1024 * KB
GB = 1024 * MB
)
func DirSize(path string) (int64, error) {
var size int64
entries, err := os.ReadDir(path)
if err != nil {
return size, err
}
for _, entry := range entries {
if entry.IsDir() {
subDirSize, err := DirSize(path + "/" + entry.Name())
if err != nil {
log.Printf("failed to calculate size of directory %s: %v\n", entry.Name(), err)
continue
}
size += subDirSize
} else {
fileInfo, err := entry.Info()
if err != nil {
log.Printf("failed to get info of file %s: %v\n", entry.Name(), err)
continue
}
size += fileInfo.Size()
}
}
return size, nil
}
func main() {
dirs := []string{"./containers", "./testfolder", "./workspace"}
for _, dir := range dirs {
size, err := DirSize(dir)
if err != nil {
log.Printf("failed to calculate size of directory %s: %v\n", dir, err)
continue
}
fmt.Printf("%s --> %.2f GB\n", dir, float64(size)/float64(GB))
}
}
这将遍历给定目录下的每个目录和文件,并汇总大小。
如果条目是目录,它将递归计算目录的大小。
虽然。。。此代码不会处理符号链接或其他特殊文件。
另一个选项用于遍历指定目录下的所有文件(包括子目录)的函数。
该函数采用两个参数:根目录和一个函数,该函数将为根目录的树中的每个文件或目录调用。DirSize
filepath.Walk
filepath.Walk
在这里,对于它遇到的每个文件,它会将文件的大小添加到总大小中(忽略目录)。
由于自动为您处理递归遍历,因此它通常比手动编写递归函数更简单、更直接。
(游乐场filepath.Walk
)
package main
import (
"os"
"log"
"fmt"
"path/filepath"
)
const (
B = 1
KB = 1024 * B
MB = 1024 * KB
GB = 1024 * MB
)
func DirSize(path string) (int64, error) {
var size int64
err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() {
size += info.Size()
}
return err
})
return size, err
}
func main() {
dirs := []string{"./containers", "./testfolder", "./workspace"}
for _, dir := range dirs {
size, err := DirSize(dir)
if err != nil {
log.Printf("failed to calculate size of directory %s: %v\n", dir, err)
continue
}
fmt.Printf("%s --> %.2f GB\n", dir, float64(size)/float64(GB))
}
}
评论
0赞
siwm
7/18/2023
感谢您的快速回复。知道了。您的意见主要是我们必须从文件中获取所有信息以计算所有目录大小。如果我理解正确的话,此外,没有关于磁盘使用的官方功能。如果您不为我做出其他响应,首先我使用本地版本更改您的代码语句,然后我会签名解决。filestate.Walk()
0赞
VonC
7/18/2023
@swim我不知道,只有。你想让我包括一个例子吗?filestate.Walk()
filepath.Walk()
filepath.Walk()
0赞
siwm
7/18/2023
对不起,我的错误:)不,没问题,但如果你想举个例子,我将不胜感激。
0赞
siwm
7/18/2023
实际上,我期待有关于磁盘使用情况的golang官方功能。
0赞
VonC
7/18/2023
@swim 我用一个例子编辑了答案filepath.Walk()
评论