如何以编程方式获取Linux中目录的可用磁盘空间?

60

是否有一种函数可以返回给定目录路径下驱动器分区上可用空间的大小?

5个回答

105

查看man statvfs(2)

我认为你可以将“可用空间”计算为f_bsize * f_bfree

NAME
       statvfs, fstatvfs - get file system statistics

SYNOPSIS
       #include <sys/statvfs.h>

       int statvfs(const char *path, struct statvfs *buf);
       int fstatvfs(int fd, struct statvfs *buf);

DESCRIPTION
       The function statvfs() returns information about a mounted file system.
       path is the pathname of any file within the mounted file  system.   buf
       is a pointer to a statvfs structure defined approximately as follows:

           struct statvfs {
               unsigned long  f_bsize;    /* file system block size */
               unsigned long  f_frsize;   /* fragment size */
               fsblkcnt_t     f_blocks;   /* size of fs in f_frsize units */
               fsblkcnt_t     f_bfree;    /* # free blocks */
               fsblkcnt_t     f_bavail;   /* # free blocks for unprivileged users */
               fsfilcnt_t     f_files;    /* # inodes */
               fsfilcnt_t     f_ffree;    /* # free inodes */
               fsfilcnt_t     f_favail;   /* # free inodes for unprivileged users */
               unsigned long  f_fsid;     /* file system ID */
               unsigned long  f_flag;     /* mount flags */
               unsigned long  f_namemax;  /* maximum filename length */
           };

8
似乎statvfs在vfat挂载的驱动器上无法工作。我尝试在FAT32分区上使用它,但可用块返回0。有方法可以解决吗? - Shadman Anwer
2
@ShadmanAnwer 不幸的是,手册上说:在所有文件系统上,返回的结构体的所有成员是否具有有意义的值都是未指定的。 因此,在这种情况下可能不支持FAT32。 - John Ledbetter
11
使用f_bsize * f_bavail以使数据与df -h命令保持一致。 - speed488
我发现f_bfree和f_bavail之间有很大的差异,这真的很奇怪,大约40%。但是像@speed488所说的那样,“df”与f_bavail一致。 - Nikolay Dimitrov
4
f_bfree 和 f_bavail 的区别是因为 ext2/3/4 文件系统为超级用户保留了一些块。这默认占据磁盘的 5% ,可以使用tune2fs命令并使用选项-r <count>-m <percentage> 来更改此值。在文件系统创建期间也可以进行设置。 - zoke

39

你可以使用 boost::filesystem 库:

struct space_info  // returned by space function
{
    uintmax_t capacity;
    uintmax_t free; 
    uintmax_t available; // free space available to a non-privileged process
};

space_info   space(const path& p);
space_info   space(const path& p, system::error_code& ec);

例子:

#include <boost/filesystem.hpp>
using namespace boost::filesystem;
space_info si = space(".");
cout << si.available << endl;
返回:一个space_info类型的对象。space_info对象的值确定方式类似于使用POSIX statvfs()获取POSIX结构体statvfs,然后将其f_blocks、f_bfree和f_bavail成员分别乘以其f_frsize成员,并将结果分配给容量、空闲和可用成员。任何无法确定值的成员都将设置为-1。

25

使用C++17

您可以使用std::filesystem::space

#include <iostream>  // only needed for screen output

#include <filesystem>
namespace fs = std::filesystem;

int main()
{
    fs::space_info tmp = fs::space("/tmp");

    std::cout << "Free space: " << tmp.free << '\n'
              << "Available space: " << tmp.available << '\n';
}

这可能需要在您的Makefile中添加链接器。我需要“-lstdc++fs”。请参见此处的注释:https://en.cppreference.com/w/cpp/filesystem - WesH

3
你可以使用Qt类QStorageInfo来获取硬盘的可用空间: 首先,你需要包含头文件:
#include <QStorageInfo> 
#define GB (1024 * 1024 * 1024)
bool CheckHardiskFree(const QString &strDisk)
{
    QStorageInfo storage(strDisk);
    if(storage.isValid() && storage.isReady())
    {
     double useGb =(storage.bytesTotal()-storage.bytesAvailable()) * 1.0/ GB;
     double freeGb =storage.bytesAvailable() * 1.0 / GB;
     double allGb =storage.bytesTotal()* 1.0 / GB;
     return true;
    }
    return false;
}

对于Qt用户非常有用 - RKum
但这对网络挂载不起作用。 - Mickaël C. Guimarães

-3

可以通过使用管道将命令的输出传递到程序中,像这样:

char cmd[]="df -h /path/to/directory" ;
FILE* apipe = popen(cmd, "r");
// if the popen succeeds read the commands output into the program with 
while (  fgets( line, 132 , apipe) )
{  // handle the readed lines
} 
pclose(apipe);
// -----------------------------------

5
打开命令会生成新的进程,这可能比C API调用慢500倍到2000倍。最终,您生成的程序也可能是用C编写的,并且您正在做很多不必要的工作。 - 15 Volts

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接