关于du 命令,这是一个用于估计文件空间使用情况的 UNIX 和 Linux 命令。du命令报告目录树的大小,包括其所有内容和单个文件的大小。
这使得它可用于追踪占用大量空间的文件,即在硬盘驱动器或其他存储介质上消耗大量或过多空间的目录和文件。
什么是目录树?
目录树是由单个目录(称为父目录或顶级目录)及其所有级别的子目录(即目录中的目录)组成的目录层次结构。任何目录都可以看作是它自己的目录树的开始,至少如果它包含子目录的话。因此,典型的计算机包含大量目录树。
大部分Linux系统是默认不安装该命令的,需要自己安装一下。
du 命令的使用
du 命令是用于报告文件系统磁盘空间使用情况的命令行实用程序。 它可用于找出文件和文件夹的磁盘使用情况并显示占用空间的内容。
du 的基本语法是:
du [选项] [目录和/或文件]
方括号中的项目是可选的。当不带选项或参数使用时,du 列出以当前目。
任何目录的空间消耗由其中所有文件及其所有级别的所有子目录占用的空间组成。报告末尾的最后一行给出了目录树的总空间消耗。
du 命令可以接受目录和目录的任意组合
du 命令可以提供有关系统上以参数形式给出名称的任何目录树或文件的信息。
上面报告当前位于 ls 目录和pwd目录两个文件的大小。
du 命令可以接受文件和目录的任意组合
du选项的使用
与 Linux 和其他类 Unix 操作系统上的大多数命令一样,du 有许多选项,其中一些是常用的。根据特定的操作系统和 du 的版本,选项可能会有所不同。
最有用的选项之一是 -h,它可以通过以千字节 (K)、兆字节 (M) 和千兆字节 (G) 而不是仅以默认千字节显示输出,从而使输出更易于阅读。
du命令可用于显示当前目录中所有子目录的大小以及当前目录的总大小,均使用适当的 K、M 或 G 格式,因此在代码中,可以这样定义宏。
/* 以可读的形式为磁盘上的文件大小设置宏 */
#define gigaByte (1 << 21) /* G 是千兆字节的输出符号 */
#define megaByte (1 << 11) /* M 是兆字节的输出符号 */
#define kiloByte (1 << 1) /* K 是千字节输出中的符号 */
-s选项告诉 du 仅报告目录树占用的总磁盘空间并抑制其子目录的单个报告。
上面的内容将以易于阅读的格式提供当前目录占用的总磁盘空间。
-a选项告诉 du 不仅要报告目录树中每个级别的每个目录的总磁盘使用量,还要报告树中任何位置的每个单独文件的空间消耗。
将列出 /etc 目录中用户具有读取权限的每个目录和文件的名称和大小。
另一个有用的选项是 --max-depth=,它指示 du 将其子目录及其大小列出到目录树中任何所需的深度级别。
与类 Unix 操作系统上的其他命令一样,du 可以通过管道链接到过滤器以创建强大的命令管道。
例如,要根据大小排列输出项,du 可以通过管道传递到 sort 命令,其 -n 选项告诉它首先按数字顺序列出最小文件的输出:
由于 du 生成的输出通常会超过一次显示器屏幕所能容纳的数量,因此输出会高速飞逝并且几乎无法读取。
du -h | less
grep 过滤器可用于在 du 的输出中搜索任何所需的字符串。
du 可用于生成目录树中消耗大量磁盘空间的目录和文件列表的一种方法是使用 grep 搜索所有包含大写字母 M 的行(即, 表示兆字节)或 G(表示千兆字节)
/*
blkcnt_t 是 中的数据类型
以可读形式计算块大小的函数 */
void blockMath(char *entryName, blkcnt_t numBlocks, int humanFlag)
{
int size;
char label;
char sizeBuf[MAX];
/* 如果未设置 -h 标志 */
if (!humanFlag)
printf("%-8ld%s\n", (numBlocks + 1) / 2, entryName);
/* 如果给出了 -h 标志,该标志以可读的形式返回输出 */
else
{
if (numBlocks >= gigaByte)
{
size = numBlocks / gigaByte;
label = 'G';
}
else if (numBlocks >= megaByte)
{
size = numBlocks / megaByte;
label = 'M';
}
else if (numBlocks >= kiloByte)
{
size = numBlocks / kiloByte;
label = 'K';
}
else
{
size = numBlocks * bytesPerBlock;
label = ' ';
}
/* 将格式化输出写入 sizeBuf,这里 10 指定写入 sizeBuf 的字节数 */
snprintf(sizeBuf, MAX, "%d%c", size, label);
printf("%-8s%s\n", sizeBuf, entryName);
}
}
/* 函数用于使用 #include 遍历目录和文件,并返回该目录的块数 */
blkcnt_t TraverseDir(char *entryName, int printFileFlag, int maxDepthFlag, int maxDepthValue, int humanFlag)
{
blkcnt_t totalSize = 0;
struct stat st;
char buffer[PATH_MAX];
DIR *dir;
struct dirent *newEntry;
/* 如果目录名称错误或路径不正确 */
if (lstat(entryName, &st))
{
perror(entryName);
exit(-1);
}
/* 用于打开和遍历目录 */
if (S_ISDIR(st.st_mode) && (dir = opendir(entryName)))
{
while ((newEntry = readdir(dir)))
if (strcmp(newEntry->d_name, ".") && strcmp(newEntry->d_name, ".."))
{
snprintf(buffer, PATH_MAX, "%s/%s", entryName, newEntry->d_name);
/* 递归调用函数直到 maxDepthValue 变为 0 */
totalSize += TraverseDir(buffer, printFileFlag, maxDepthFlag, maxDepthValue - 1, humanFlag);
}
closedir(dir);
}
/* 添加块大小 */
totalSize += st.st_blocks;
if ((printFileFlag || S_ISDIR(st.st_mode)) && (maxDepthValue >= 0 || !maxDepthFlag))
blockMath(entryName, totalSize, humanFlag);
return totalSize; /* 返回块数 */
}
总结
du 命令通常被系统管理员用作自动监控和通知程序的补充,有助于防止关键目录和分区变满。已满或几乎已满的目录和分区会导致系统变慢,阻止用户登录,甚至导致系统崩溃。
du 命令只能用于估计用户具有读取权限的目录和文件的空间消耗。因此,普通用户通常无法使用 du 来确定属于其他用户的文件或目录的空间消耗,包括属于 root 帐户的文件或目录。