Я пытаюсь написать базовую программу, которая суммирует файлы всех файлов в текущем каталоге и во всех подкаталогах. Я думал, что это будет отличное упражнение. Я пытаюсь использовать базовую рекурсию для этого. Вот то, что я до сих пор:Написание простой клон. Получение случайных значений для файлов в подкаталогах.
#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;
}
Вот мой вывод программы (я также с включением в Ls поддиректории)
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$
В моем ограниченном опыте, получение случайных данных является признаком неправильного выделение памяти, но st_size в структуре stat является длинным int ..?
Посмотрите на ['nftw()'] (http://pubs.opengroup.org/onlinepubs/9699919799/functions/nftw.html), чтобы упростить некоторые части вашей работы. –
Обратите внимание, что 'stat (de-> d_name, &s); if (S_ISLNK (s.st_mode))' никогда не обнаружит символическую ссылку, вы должны использовать 'lstat()', чтобы увидеть ссылку как ссылку. ('Stat() 'следует символической ссылке на свой горький конец,' lstat() 'говорит, что запись является символической ссылкой, если она есть, и в противном случае ведет себя как' stat() '. –
Было бы разумно использовать' snprintf() 'для объединения каталог и имя файла, что предотвращает переполнение буфера.Конечно, вам также нужно проверить, завершено ли копирование. –