Linux下获得磁盘和目录大小

一、磁盘容量

在Linux的系统中,如何获取磁盘的容易。最容易的方法是使用命令:

lsblk -o NAME,SIZE    [lsblk --all]
...
sda         931.5G
├─sda1        500G
└─sda2      431.5G
nvme0n1     476.9G
├─nvme0n1p1   512M
└─nvme0n1p2 476.4G

....

或者:
df -h
文件系统        大小  已用  可用 已用% 挂载点
tmpfs           3.2G  2.6M  3.2G    1% /run
/dev/nvme0n1p2  468G  297G  148G   67% /
tmpfs            16G  107M   16G    1% /dev/shm
tmpfs           5.0M  4.0K  5.0M    1% /run/lock
/dev/nvme0n1p1  511M  6.1M  505M    2% /boot/efi
/dev/sda2       424G   56G  347G   14% /mnt/data
tmpfs           3.2G  164K  3.2G    1% /run/user/1000
/dev/sda1       500G   14G  487G    3% /media/fpc/D42E48EB2E48C866

其它还有很多,比如fdisk 或 parted(可能需要sudo权限),blockdev,vgs ,lvs,smartctl等等。当然也可以使用du命令来查看具体某个路径的大小空间容量:

du -sh /usr
19G	/usr

但是如果想在程序里获取相关的磁盘的目录和磁盘大小呢?当然也可以采用执行命令的方法,去拿返回值。其实在Linux中也提供了相关的函数接口的。

二、获得磁盘大小的方法

在POSIX中提供了一个比较简单的接口statvfs,它的定义如下:

struct statvfs
  {
    unsigned long int f_bsize;//文件系统块大小(file system block size)
    unsigned long int f_frsize;//碎片段大小(fragment size)
#ifndef __USE_FILE_OFFSET64
    __fsblkcnt_t f_blocks;
    __fsblkcnt_t f_bfree;
    __fsblkcnt_t f_bavail;
    __fsfilcnt_t f_files;
    __fsfilcnt_t f_ffree;
    __fsfilcnt_t f_favail;
#else
    __fsblkcnt64_t f_blocks;//块单元数量(size of file system in f_frsize units)
    __fsblkcnt64_t f_bfree;//空闲块
    __fsblkcnt64_t f_bavail;//空闲块(用户)
    __fsfilcnt64_t f_files;
    __fsfilcnt64_t f_ffree;//空闲节点
    __fsfilcnt64_t f_favail;//空闲节点(用户)
#endif
    unsigned long int f_fsid;
#ifdef _STATVFSBUF_F_UNUSED
    int __f_unused;
#endif
    unsigned long int f_flag;
    unsigned long int f_namemax;
    int __f_spare[6];
  };
#ifdef __USE_LARGEFILE64
struct statvfs64
  {
    unsigned long int f_bsize;
    unsigned long int f_frsize;
    __fsblkcnt64_t f_blocks;
    __fsblkcnt64_t f_bfree;
    __fsblkcnt64_t f_bavail;
    __fsfilcnt64_t f_files;
    __fsfilcnt64_t f_ffree;
    __fsfilcnt64_t f_favail;
    unsigned long int f_fsid;
#ifdef _STATVFSBUF_F_UNUSED
    int __f_unused;
#endif
    unsigned long int f_flag;
    unsigned long int f_namemax;
    int __f_spare[6];
  };
#endif

一般来说,f_bsize和f_frsize的大小相同。而f_bfree和f_bavail的表现则略有不同。可能会有较大的误差,后者可能更接近于实际情况。所以大家可以根据实际情况来操作磁盘空间的大小显示。
它还有两个类似的相关接口fstatvfs和fstatvfs64,有兴趣的可以看看帮助文档。

三、例程

在实际编写程序时,有一个问题需要说明。并不是说使用设备名字来获得空间大小,这个误差相当大。它需要使用挂载点(mount point)来处理,则就基本正常了。所以代码中需要一个动态转换或者说获取挂载点的过程,看下面的代码:

#ifndef __DISKCAPACITY_H__
#define __DISKCAPACITY_H__

#include <string>
#include <unordered_map>
#include <vector>

namespace archive {
struct DevInfo {
  std::string devPath;
  std::string mountPoint;
  std::string type;
  uint64_t totalSize;
  uint64_t freeSize;
};
class DiskCapacity {
public:
  DiskCapacity();

public:
  bool initDiskCapacity();
  std::unordered_map<std::string, uint64_t> getDiskCapacity();

private:
  std::vector<DevInfo> getCapacityFromMountPoint();

private:
  DevInfo m_devInfo;
  std::vector<DevInfo> m_vecDevInfo;
};
} // namespace archive
#endif // __DISKCAPACITY_H__
//cpp
#include "DiskCapacity.h"
#include <fcntl.h>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <linux/fs.h>
#include <sstream>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <unistd.h>

namespace fs = std::filesystem;

namespace archive {
DiskCapacity::DiskCapacity() {}
bool DiskCapacity::initDiskCapacity() { return true; }
//!
//! \brief DiskCapacity::getDiskCapacity
//! \return unordered_map:devPath:/dev/xxx ,capacity(uint64_t):M(K,M,G,T)
//!
std::unordered_map<std::string, uint64_t> DiskCapacity::getDiskCapacity() {
  std::unordered_map<std::string, uint64_t> umDev;
  auto vec = this->getCapacityFromMountPoint();
  for (auto &au : vec) {
    umDev.emplace(au.devPath, au.freeSize);
  }
  return umDev;
}
std::vector<DevInfo> DiskCapacity::getCapacityFromMountPoint() {
  struct statvfs fsStat;
  std::string devAllPath = R"path(/dev/)path";

  for (const auto &entry : fs::directory_iterator(devAllPath)) {
    std::string path = devAllPath;
    // ignore directory and non block devives
    if (entry.is_directory() || strncmp(path.c_str(), "sd", 2) != 0) {
      continue;
    }

    path += entry.path().string();

    struct stat st;
    if (stat(path.c_str(), &st) == 0 && S_ISBLK(st.st_mode)) {
      DevInfo devInfo;
      devInfo.devPath = path;

      std::string mountPoint = R"point(/proc/mounts)point";
      std::ifstream mounts(mountPoint);
      std::string line;

      while (std::getline(mounts, line)) {
        std::istringstream iss(line);
        std::string dev, mPoint, fType;
        iss >> dev >> mPoint >> fType;

        devInfo.mountPoint = mPoint;
        devInfo.type = fType;

        if (statvfs(devInfo.mountPoint.c_str(), &fsStat) == 0) {
          devInfo.totalSize = static_cast<unsigned long long>(fsStat.f_blocks) * fsStat.f_frsize;
          devInfo.freeSize = static_cast<unsigned long long>(fsStat.f_bavail) * fsStat.f_frsize;
        }
        break;
      }

      m_vecDevInfo.emplace_back(devInfo);
    }
  }
  return m_vecDevInfo;
}
} // namespace archive

代码并不复杂,这里就不再分析了。
在Linux及相关的环境中,还有其它相关的函数也可以达到类似的目的,如statfs(BSD,Linux),所以到罗马的大路有很多条,就看哪个合适即可。

四、总结

这种小问题,往往需要重复的造轮子。这个小总结就算给大家重复造轮子时的一个借鉴吧。

<think>我们有两个主要任务:1.查看磁盘总容量剩余空间(使用df命令)2.找出指定目录(通常是根目录或当前目录)下占用空间最大的前十个目录或文件(使用du命令结合排序)根据引用[3],我们可以使用`df -h`来查看磁盘总容量剩余空间。根据引用[1][2],我们可以使用`du`命令来查看目录大小,并通过排序来得到最大的目录或文件。具体步骤:一、查看磁盘总容量剩余空间命令:`df -h`二、找出占用空间最大的目录或文件1.进入目标目录,比如根目录`/`,或者指定目录。2.使用`du`命令计算每个子目录或文件的大小,然后排序取前10。注意:由于权限问题,可能需要使用`sudo`。推荐命令:```bash#查看当前目录下各个子目录/文件的大小(包括隐藏文件),并排序取前10du -ah .| sort-rh| head-n10或者#仅查看当前目录下子目录(不包括文件)的大小,并排序取前10du -sh *| sort-rh| head-n10```但是,上述命令可能无法处理文件名中的空格等特殊字符,且`du -ah`会列出所有文件,可能会非常多,导致排序慢。因此,我们更推荐使用:```bash#查找指定目录下(例如/)占用空间最大的前10个目录(不包括文件)sudo du-h/ |sort -rh |head -n10```或者,如果我们想同时包含文件,并且希望更精确地控制深度(避免列出太多层级),可以使用:```bash#查找指定目录下(例如/home)占用空间最大的前10个文件或目录(深度为1)sudo du-h--max-depth=1 /home |sort -rh |head -n10```注意:`sort-rh`中的`-h`选项可以处理人类可读的大小(如1K,2M,3G),但需要确保你的sort版本支持(GNU sort支持)。如果系统不支持`-h`参数(如macOS的sort),则可以使用:```bashsudodu -k/ |sort -nr |head -n10```这样会以KB为单位,然后按数字倒序排列。三、综合步骤1.首先,使用`df-h`查看整体磁盘使用情况。2.然后,使用`du`命令找出占用空间最大的目录或文件。四、注意事项-使用`sudo`是因为有些目录需要权限才能访问。-如果目录很大,`du`可能需要一些时间。因此,完整的回答如下:</think>### 📊 Linux 查看磁盘容量空间占用分析指南 #### 🔍 一、查看磁盘总容量剩余空间 ```bash df -h ``` - **作用**:显示所有挂载点的磁盘使用情况 - **输出字段**: - `Filesystem`:分区名称 - `Size`:总容量 - `Used`:已用空间 - `Avail`:可用空间 - `Use%`:使用百分比 - `Mounted on`:挂载路径 - **示例输出**: ``` Filesystem Size Used Avail Use% Mounted on /dev/sda1 98G 45G 48G 48% / /dev/sdb1 1.8T 1.2T 512G 70% /data ``` #### 📂 二、查找占用空间最大的目录/文件 ```mermaid graph TD A[目标目录] --> B[计算各目录大小] B --> C[按大小排序] C --> D[取前10名] ``` ##### 方法1:当前目录下前十大目录 ```bash du -h --max-depth=1 | sort -rh | head -n 10 ``` - **参数说明**: - `--max-depth=1`:只统计一级子目录 - `sort -rh`:按人类可读数值逆序排序 - `head -n 10`:取前10行 ##### 方法2:系统范围前十大目录(需root权限) ```bash sudo du -h / --max-depth=1 2>/dev/null | sort -rh | head -n 10 ``` - **注意**:`2>/dev/null` 用于忽略权限错误提示 ##### 方法3:精确查找前十大文件 ```bash sudo find / -type f -exec du -h {} + 2>/dev/null | sort -rh | head -n 10 ``` #### 🔧 三、实用组合命令 ##### 1. 分析指定目录(如/home)的空间占用 ```bash sudo du -h /home --max-depth=1 | sort -rh | head -n 10 ``` ##### 2. 可视化目录大小(需安装ncdu) ```bash sudo apt install ncdu ncdu / ``` - 交互式界面支持方向键导航删除操作 ##### 3. 按文件类型统计空间 ```bash # 统计当前目录下各类文件占用空间 find . -type f -printf "%f %s\n" | awk '{ ext = $1; sub(/^.*\./, "", ext); size[$ext] += $2 } END { for (i in size) printf "%s\t%.2f MB\n", i, size[i]/1048576 }' | sort -k2 -nr ``` #### ⚠️ 四、注意事项 1. **权限问题**:系统目录需`sudo`权限 2. **排除挂载点**:使用`-x`参数避免跨文件系统统计 ```bash sudo du -h -x / --max-depth=1 ``` 3. **大目录处理**:对TB级目录添加`--time`参数查看耗时 ```bash time sudo du -sh /large_directory ``` #### 📊 五、输出结果示例 ``` 4.5G /var 3.2G /usr 1.8G /home 890M /opt 550M /etc 320M /tmp 120M /boot 85M /root 45M /bin 32M /sbin ``` > 关键技巧:**组合使用`du`的深度控制`sort`的数值排序**可快速定位空间占用热点[^2]。对于生产环境,建议定期使用`ncdu`进行可视化分析[^1]。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值