如何让一个目录的大小编程在linux?(how to get the size of a dir p

2019-09-18 23:12发布

我想通过一个C程序来获得在Linux中特定目录的确切大小。 我尝试使用的statfs(路径,结构的statfs&),但它没有给出确切大小。 我也试图与统计(),但它返回的尺寸为4096的任何目录!

请给我建议,通过它我可以得到目录的确切大小就像我们后“杜-SH dirPath”命令获取的方式。

此外,我不通过系统想用杜()。

提前致谢。

Answer 1:

典型的解决方案

如果你想有一个目录,在时尚类似于杜的大小,创建一个递归函数。 这是可能的迭代解决问题,但解决方案适合于递归。

信息

这里是一个链接,让你开始:

http://www.cs.utk.edu/~plank/plank/classes/cs360/360/notes/Prsize/lecture.html

搜索

谷歌搜索与“统计C程序递归目录大小”

直接从吉姆·普朗克网站,作为一个例子让你开始。

#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>

main()
{
  DIR *d;
  struct dirent *de;
  struct stat buf;
  int exists;
  int total_size;

  d = opendir(".");
  if (d == NULL) {
    perror("prsize");
    exit(1);
  }

  total_size = 0;

  for (de = readdir(d); de != NULL; de = readdir(d)) {
    exists = stat(de->d_name, &buf);
    if (exists < 0) {
      fprintf(stderr, "Couldn't stat %s\n", de->d_name);
    } else {
      total_size += buf.st_size;
    }
  }
  closedir(d);
  printf("%d\n", total_size);
}


Answer 2:

你需要STAT()中的所有文件在当前目录和子目录,并把它们加起来。

请考虑使用递归算法这一点。



Answer 3:

如果你不希望使用'system' ,而是确定使用'pipe''fork''execlp''du' ,你可以建立一个管道,一个新的进程,重定向'STDOUT'孩子在管,EXEC 'du'的孩子,并读取结果父。 样品代码将是:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void) {
  int pfd[2], n;
  char str[1000];

  if (pipe(pfd) < 0) {
    printf("Oups, pipe failed.  Exiting\n");
    exit(-1);
  }

  n = fork();

  if (n < 0) {
    printf("Oups, fork failed.  Exiting\n");
    exit(-2);
  } else if (n == 0) {
    close(pfd[0]);

    dup2(pfd[1], 1);
    close(pfd[1]);

    execlp("du", "du", "-sh", "/tmp", (char *) 0);
    printf("Oups, execlp failed.  Exiting\n"); /* This will be read by the  parent. */
    exit(-1); /* To avoid problem if execlp fails, especially if in a loop. */
  } else {
    close(pfd[1]);

    n = read(pfd[0], str, 1000); /* Should be done in a loop until read return 0, but I am lazy. */
    str[n] = '\0';

    close(pfd[0]);
    wait(&n); /* To avoid the zombie process. */

    if (n == 0) {
       printf("%s", str);
    } else {
       printf("Oups, du or execlp failed.\n");
    }
  }
}


Answer 4:

我猜的解决方案可能是为那些谁仍可能会遇到的问题是有用的。

下面是被写入模仿Linux的功能du项目。 它递归遍历所有目录,并增加了文件大小。

请注意 ,这个功能仍然是不完整的,因为它不正确的行为的硬链接。 每个人都应该添加一个容器来存储文件描述符指向同一个inode的实体并用它来摆脱非常同一文件的多个计数。 lstat()是用来处理符号链接(也称为软链接), 硬链接是一个问题在这里

size_t countDiskUsage(const char* pathname)
{
  if (pathname == NULL) {
    printf("Erorr: pathname is NULL\n");
  }

  struct stat stats;

  if (lstat(pathname, &stats) == 0) {
    if (S_ISREG(stats.st_mode)){
      return stats.st_size;
    }
  } else {
    perror("lstat\n");
  }

  DIR* dir = opendir(pathname);

  if (dir == NULL) {
    perror("Error");
    return 0;
  }

  struct dirent *dirEntry;
  size_t totalSize = 4096;

  for (dirEntry = readdir(dir); dirEntry != NULL; dirEntry =   readdir(dir)) {
    long pathLength = sizeof(char) * (strlen(pathname) + strlen(dirEntry->d_name) + 2);
    char* name = (char*)malloc(pathLength);
    strcpy(name, pathname);
    strcpy(name + strlen(pathname), "/");
    strcpy(name + strlen(pathname) + 1, dirEntry->d_name);

    if (dirEntry->d_type == DT_DIR) {
      if (strcmp(dirEntry->d_name, ".") != 0 && strcmp(dirEntry->d_name, "..") != 0) {
        totalSize += countDiskUsage(name);
      }
    } else {
      int status = lstat(name, &stats);
      if (status == 0) {
        totalSize += stats.st_size;
      } else {
        perror("lstat\n");
      }
    }
    free(name);
  }

  closedir(dir);

  return totalSize;
}


文章来源: how to get the size of a dir programatically in linux?
标签: c linux size dir