2014-02-07 39 views
1

有沒有辦法獲得遞歸的子目錄的總大小?如何獲取C中子目錄的總大小?

例如:

Dir1 
-- FileA.txt (90) 
-- SubDir2 (4096) 
---- FileB.txt (100) 
---- FileC.txt (400) 

當我試圖讓SubDir2的大小,它給了我4186預期的答案,我希望得到的是4596.

我的程序計算FILEA的大小而不是FileB和FileC。如何使它計數FileB和FileC?

首先,我必須使用這些標頭:

#include <errno.h> 
#include <stdio.h> 
#include <sys/types.h> 
#include <dirent.h> 
#include <sys/stat.h> 
#include <unistd.h> 
#include <string.h> 

於是,我做了這個函數遞歸調用它:

static DIR *dir; 

void goDir(char* argv[]) 
{ 
    struct dirent *dit; 
    struct stat st; 

    int size = 0; 
    static int total_size = 0; 

    char filePath[NAME_MAX]; 

    while ((dit = readdir(dir)) != NULL) 
    { 
     sprintf(filePath, "%s/%s", argv[1], dit->d_name); // To show correctly the size and name of files 
     lstat(filePath, &st); 
     // To skip . and .. 
     if ((strcmp(dit->d_name, ".") == 0) || (strcmp(dit->d_name, "..") == 0)) continue; 

     size = st.st_size; 

     if(S_ISDIR(st.st_mode)) 
     { 
      goDir(argv); // For Recursivity 

      total_size += size; 

      printf("DIR\t");    
      printf("MODE: %lo\t", (unsigned long) st.st_mode); 
      printf("SIZE: %d\t", total_size); 
      printf("%s\n", dit->d_name); 
     } 
     else 
     { 
      total_size += size; 

      printf("FILES\t"); 
      printf("MODE: %lo\t", (unsigned long) st.st_mode); 
      printf("SIZE: %d\t", size); 
      printf("%s\n", dit->d_name); 
     } 

    } 

} 

然後,我的主要程序:

int main (int argc, char *argv[]) 
{ 
    if (argc != 2) { 
     printf("Usage: Program <Directory>\n"); 
     return 1; 
    } 

    if ((dir = opendir(argv[1])) == NULL) return 1; 

    goDir(argv); 
    closedir(dir); 

    return 0; 
} 
+0

您目前無法顯示子目錄的總大小,因爲您只保留目前爲止所看到的所有項目的大小(您的靜態'total_size'變量)的總計大小。你想要做的是讓你的函數返回它檢查的目錄的總大小。 –

回答

2

你的goDir()函數永遠不會打開一個新的目錄,或者一旦它完成就關閉該目錄。這會導致問題 - 基本上,你沒有遍歷你的目錄層次結構。

您需要在goDir()函數中將dir設爲本地(非static)變量;你會打開和關閉目錄;和強似argv,你會經過一個目錄名等

當你在這,你應該改變goDir()返回它找到的大小,而失去static變量total_size

此代碼看起來半似是而非:

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

#ifndef NAME_MAX 
#define NAME_MAX 1024 
#endif 

static long goDir(char *dirname) 
{ 
    DIR *dir = opendir(dirname); 
    if (dir == 0) 
     return 0; 

    struct dirent *dit; 
    struct stat st; 
    long size = 0; 
    long total_size = 0; 
    char filePath[NAME_MAX]; 

    while ((dit = readdir(dir)) != NULL) 
    { 
     if ((strcmp(dit->d_name, ".") == 0) || (strcmp(dit->d_name, "..") == 0)) 
      continue; 

     sprintf(filePath, "%s/%s", dirname, dit->d_name); 
     if (lstat(filePath, &st) != 0) 
      continue; 
     size = st.st_size; 

     if (S_ISDIR(st.st_mode)) 
     { 
      long dir_size = goDir(filePath) + size; 
      printf("DIR\t"); 
      printf("MODE: %lo\t", (unsigned long) st.st_mode); 
      printf("SIZE: %ld\t", dir_size); 
      printf("%s\n", filePath); 
      total_size += dir_size; 
     } 
     else 
     { 
      total_size += size; 
      printf("FILES\t"); 
      printf("MODE: %lo\t", (unsigned long) st.st_mode); 
      printf("SIZE: %ld\t", size); 
      printf("%s\n", filePath); 
     } 
    } 
    return total_size; 
} 

int main(int argc, char *argv[]) 
{ 
    if (argc != 2) 
    { 
     fprintf(stderr, "Usage: %s <Directory>\n", argv[0]); 
     return 1; 
    } 

    long size = goDir(argv[1]); 
    printf("Total size: %ld\n", size); 

    return 0; 
} 

它編譯和運行。它沒有給出與du -k相同的答案,主要是因爲它沒有將文件大小累加到整數個磁盤塊。您需要查看struct stat中的st_blksize和/或st_blocks以獲取該信息。

+0

我注意到當我添加一個新的空子目錄時,疊加起來的總和。 (SubDir2 +新的SubDir3)。 –

+0

我想知道如果添加total_size = 0; if(S_ISDIR(st.st_mode)){}是一個好主意。它似乎解決了這個問題,但它有一個小錯誤。但是,謝謝你的修正。 –

+0

我改變了目錄大小的計算和打印。是的,這不是最優的 - 它基於你的原始代碼太密切。 –

0

您必須使用散列表來跟蹤inode的出現次數。所以他們不算兩次。