oprofile, без сомнения; его простое, надежное, делают задание и могут дать все виды хороших разбивок данных.
stat также работает с каталогами.
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
int num_dirs(const char* path)
{
int dir_count = 0;
struct dirent* dent;
DIR* srcdir = opendir(path);
if (srcdir == NULL)
{
perror("opendir");
return -1;
}
while((dent = readdir(srcdir)) != NULL)
{
struct stat st;
if(strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0)
continue;
if (fstatat(dirfd(srcdir), dent->d_name, &st, 0) < 0)
{
perror(dent->d_name);
continue;
}
if (S_ISDIR(st.st_mode)) dir_count++;
}
closedir(srcdir);
return dir_count;
}
/*
I had need in something like this not so long ago (my difference is I
needed recursive scan) so I added only some comments... Sorry for recursion
but I was short of time and this was only part of internal one-time tool.
*/
/* Print all the dirs starting from <path> [maybe recursive]. */
int print_dirs(const char *path, int recursive)
{
struct dirent *direntp = NULL;
DIR *dirp = NULL;
size_t path_len;
/* Check input parameters. */
if (!path)
return -1;
path_len = strlen(path);
if (!path || !path_len || (path_len > _POSIX_PATH_MAX))
return -1;
/* Open directory */
dirp = opendir(path);
if (dirp == NULL)
return -1;
while ((direntp = readdir(dirp)) != NULL)
{
/* For every directory entry... */
struct stat fstat;
char full_name[_POSIX_PATH_MAX + 1];
/* Calculate full name, check we are in file length limts */
if ((path_len + strlen(direntp->d_name) + 1) > _POSIX_PATH_MAX)
continue;
strcpy(full_name, path);
if (full_name[path_len - 1] != '/')
strcat(full_name, "/");
strcat(full_name, direntp->d_name);
/* Ignore special directories. */
if ((strcmp(direntp->d_name, ".") == 0) ||
(strcmp(direntp->d_name, "..") == 0))
continue;
/* Print only if it is really directory. */
if (stat(full_name, &fstat) < 0)
continue;
if (S_ISDIR(fstat.st_mode))
{
printf("%s\n", full_name);
if (recursive)
print_dirs(full_name, 1);
}
}
/* Finalize resources. */
(void)closedir(dirp);
return 0;
}
/* We are taking first argument as initial path name. */
int main(int argc, const char* argv[])
{
if (argc < 2)
return -1;
print_dirs(argv[1], 1);
return 0;
}
Как отмечали другие, stat (2)
отлично работает с файлами и устройствами всех типов. Он читает через символические ссылки на файл на дальнем конце; если вам нужна информация о самой символической ссылке, используйте lstat (2)
.
Чтобы перечислить имена всех каталогов в одном каталоге (нерекурсивно), используйте комбинацию ] readdir (3)
семейство функций.
Чтобы перечислить имена всех каталогов рекурсивно, используйте функции ftw (3)
или nftw (3)
для выполнения «обход файлового дерева» (отсюда и их имена; «n» означает «новый»).