C - игнорировать имена подкаталогов и печатать только имена файлов - PullRequest
0 голосов
/ 16 февраля 2019

С помощью этого кода я могу рекурсивно печатать все файлы и подкаталоги по заданному пути.

Я хочу игнорировать (не печатать) все имена подкаталогов и печатать только имена файлов.

Это код:

#include <stdio.h>
#include <dirent.h>
#include <string.h> 


void listFilesRecursively(char *basePath)
{
    char path[1000];
    struct dirent *dp;
    DIR *dir = opendir(basePath);

    if (!dir)
        return;

    while ((dp = readdir(dir)) != NULL)
    {
        if (strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0)
        {
            strcpy(path, basePath);
            strcat(path, "/");
            strcat(path, dp->d_name);

            listFilesRecursively(path);
            printf("%s\n", path);
        }
    }

    closedir(dir);
}

int main()
{
    char path[100];

    printf("Enter path to list files: ");
    scanf("%s", path);

    listFilesRecursively(path);

    return 0;
}

1 Ответ

0 голосов
/ 16 февраля 2019

Существуют макросы, которые сообщают вам, какой это тип файла:

  • S_ISREG(): обычный файл
  • S_ISDIR(): файл каталога
  • S_ISCHR(): специальный символьный файл
  • S_ISBLK(): специальный файл блока
  • S_ISFIFO(): канал или FIFO - S_ISLNK(): символьный
  • S_ISSOCK(): сокет ссылки

Прежде всего вы можете использовать одну из следующих функций для получения информации:

#include <sys/stat.h>
int stat(const char *restrict pathname, struct stat *restrict buf );
int fstat(int fd, struct stat *buf);
int lstat(const char *restrict pathname, struct stat *restrict buf );
int fstatat(int fd, const char *restrict pathname, struct stat *restrict buf, int flag);

Из книги «Расширенное программирование в среде Unix»:

По заданному пути функция stat возвращает структуру информации об указанном файле.Функция fstat получает информацию о файле, который уже открыт по дескриптору fd.Функция lstat аналогична stat, но когда указанный файл является символической ссылкой, lstat возвращает информацию о символической ссылке, а не о файле, на который ссылается символическая ссылка.

Вы можете попробовать что-то вродеследующее:

struct stat statbuf;
struct dirent *dirp;
DIR *dp;
int ret, n;
/* fullpath contains full pathname for every file */
if (lstat(fullpath, &statbuf) < 0)
{
    printf("error\n");
    //return if you want
}
if (S_ISDIR(statbuf.st_mode) == 0)
{
   /* not a directory */
}
else
{
   //a directory
}

Исторически в ранних версиях UNIX System не было макросов S_ISxxx.Вместо этого нам пришлось логически AND значение st_mode с маской S_IFMT, а затем сравнить результат с константами, имена которых S_IFxxx.Большинство систем определяют эту маску и соответствующие константы в файле.

Например:

struct stat *statptr;
if (lstat(fullpath, statptr) < 0)
{
    printf("error\n");
    //return if you want
}
switch (statptr->st_mode & S_IFMT) {
    case S_IFREG:  ...
    case S_IFBLK:  ...
    case S_IFCHR:  ...
    case S_IFIFO:  ...
    case S_IFLNK:  ...
    case S_IFSOCK: ... 
    case S_IFDIR:  ... 
    }
...