2011-12-31 7 views
3

私は現在のディレクトリとすべてのサブディレクトリ内のすべてのファイルのファイルサイズを合計する基本的なプログラムを作成しようとしています。私はそれが素晴らしい運動だと思った。私はこれのために基本的な再帰を使用しようとしています。ここで私はこれまで持っているものである:ここでは シンプルなデュクローンを書く。サブディレクトリ内のファイルサイズのランダムな値を取得します。

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

long totalbytes = 0; 

long dirsize(const char* directory, int verbose) 
{ 
    struct dirent *de; 
    struct stat s; 
    DIR * dir; 
    //long total_items = 0; 
    long filesize = 0; 

    dir = opendir(directory); 
    if (dir == NULL) 
    { 
    printf("Failed to open %s.\n", directory); 
    return -1; 
    } 

    while ((de = readdir (dir)) != NULL) 
    { 
    stat(de->d_name, &s); 
    if (S_ISLNK(s.st_mode)) 
    { 
    printf("links are ignored.\n"); 
    } 
    if (de->d_type == DT_REG) 
    { 
    filesize = 0; //be sure to reset this each time to avoid inaccuracy 
    stat(de->d_name, &s); // get file info into our s structure 
    if (verbose) 
    { 
     printf("%s/%s : %ld bytes (%f MB)\n", directory, de->d_name, s.st_size, (float) s.st_size/1024/1024); 
    } 
    filesize = s.st_size; //put file size into filesize variable 
    totalbytes += filesize; //increment totalbytes 
    } 
    if (de->d_type == DT_DIR && strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..") != 0) 
    { 
    char pathname[PATH_MAX]; 
    sprintf(pathname, "%s/%s", directory, de->d_name); 
    dirsize(pathname, verbose); //recursion: keep looping until no more subdirs remain 
    } 
    } 
    closedir(dir); 
    return totalbytes; 
} 

long compute_size(const char* directory, int verbose) 
{ 
    long space = dirsize(directory, verbose); 
    return space; 
} 

int main(int argc, char* argv[]) 
{ 
    if (argc != 2) 
    { 
    printf("Usage: dirsize DIRECTORY\n"); 
return -1; 
    } 

    int verbose = 1; //show or hide individual computations 

    long space = compute_size(argv[1], verbose); 
    if (space != -1) 
    { 
    float space_mb = (float) space/1024/1024; 
    printf("space occupied: %ld bytes\n", space); 
    printf("(%f MB)\n", space_mb); 
    } 
    return 0; 
} 

は、私の限られた経験で

08:35 [email protected]~/tmp$ ./dirsize . 
./dirsize : 8369 bytes (0.007981 MB) 
./diskstat.c : 1430 bytes (0.001364 MB) 
./diskstat : 7993 bytes (0.007623 MB) 
./ftw.c : 491 bytes (0.000468 MB) 
./a.out : 8044 bytes (0.007671 MB) 
./arrays.sh : 212 bytes (0.000202 MB) 
./fileread/timestamp : 0 bytes (0.000000 MB) 
./fileread/timestamp.c : 0 bytes (0.000000 MB) 
./fileread/a.out : 8044 bytes (0.007671 MB) 
./fileread/build.prop : 8044 bytes (0.007671 MB) 
./fileread/read.c : 4096 bytes (0.003906 MB) 
./fileread/read : 454656 bytes (0.433594 MB) 
./local.fstab : 76 bytes (0.000072 MB) 
./dirsize.c : 1857 bytes (0.001771 MB) 
./echo.sh : 223 bytes (0.000213 MB) 
./TEAMS.sh : 605 bytes (0.000577 MB) 
space occupied: 504140 bytes 
(0.480785 MB) 
08:35 [email protected]~/tmp$ ls -l fileread/ 
total 40 
-rwxr-xr-x 1 raidzero raidzero 8132 Dec 28 10:39 a.out 
-rw-r--r-- 1 raidzero raidzero 2346 Dec 28 10:09 build.prop 
-rwxr-xr-x 1 raidzero raidzero 8384 Dec 29 13:57 read 
-rw-r--r-- 1 raidzero raidzero 1150 Dec 28 10:16 read.c 
-rwxr-xr-x 1 raidzero raidzero 8132 Dec 29 13:57 timestamp 
-rw-r--r-- 1 raidzero raidzero 659 Dec 28 10:39 timestamp.c 
08:35 [email protected]~/tmp$ 

(私もサブディレクトリのLSを含めています)私のプログラムの出力であるランダムなデータを取得することは不適切の兆候でありますメモリの割り当てが、st_sizeのstat構造体は長いintです..?

+0

['nftw()'](http://pubs.opengroup.org/onlinepubs/9699919799/functions/nftw.html)を見ると、仕事の一部をよりシンプルにすることができます。 –

+0

'stat(de-> d_name、&s); if(S_ISLNK(s.st_mode))'はシンボリックリンクを見つけられないのでリンクをリンクとして見るには 'lstat()'を使う必要があることに注意してください。 'lstat()'はエントリがシンボリックリンクであれば '' stat() ''のように振る舞います。 –

+0

'snprintf()'を使うと賢明です –

答えて

2

​​は、ファイル名のみを持ちます。これまでのパスは含まれていません。たとえば、./fileread/timestampではなく、./timestampのように制作しています。ファイルの絶対パスを作成するか、chdir()を使用してディレクトリを入力します(マルチスレッド環境の場合は安全ではありません。ディレクトリに移動している場合は壊れやすくなる可能性があります)。fchdir()上位のディレクトリに戻すのに非常に役立つ)、または(最近のunixenの場合)openat()/fstat()関数を使用してディレクトリをトラバースします。

statからのエラーが返ってきたことを確認した場合は、これに気づいたでしょう。これらのエラーの戻りを常に確認してください。

+0

私はsprintfを使ってファイルへのパスを作成しましたが、ここでは 'sprintf(pathname、"%s /%s "、ディレクトリ、de - > d_name);'(少なくとも私の意図だった) – raidzero

+0

リターンコード、良いヒントをチェックします:D – raidzero

+0

@raidzero、これはサブディレクトリに再帰するときに行いますが、raw 'de-> d_name'の値 – bdonlan

関連する問題