Domanda

C'è un modo per elencare tutte le sottodirectory di un dato percorso di directory in C? Speravo che sarei in grado di farlo con la funzione stat() ma funziona solo su file.

È stato utile?

Soluzione

stat lavora su directory troppo.

#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;
}

Altri suggerimenti

Si vuole readdir (3) .

Come altri hanno notato, stat(2) funziona bene su file e dispositivi di tutti i tipi. Si legge tramite link simbolico al file in fondo; se avete bisogno di informazioni relative al link simbolico stesso, utilizzare lstat(2).

Per elencare i nomi di tutte le directory all'interno di una singola directory (non ricorsivo), utilizzare una combinazione di famiglia readdir(3) di funzioni.

Per elencare i nomi di tutte le directory ricorsivamente, utilizzare le funzioni ftw(3) o nftw(3) di fare un 'albero camminata file' (da dove vien loro nomi; 'n' è per 'nuovo').

/*
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;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top