C: проверка типа файла.Использование lstat () и макросов не работает - PullRequest
5 голосов
/ 06 октября 2011

Я использую opendir (), чтобы открыть каталог, а затем readdir () и lstat (), чтобы получить статистику каждого файла в этом каталоге. После этого manpage я написал код, который работает не так, как задумывалось. Он выводит список всех файлов в текущем каталоге, но не распечатывает, является ли файл обычным файлом, символической ссылкой или каталогом.

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

void main(){

    char* folder=".";                                     //folder to open

    DIR* dir_p;
    struct dirent* dir_element;
    struct stat file_info;

    // open directory
    dir_p=opendir(folder);

    // show some info for each file in given directory
    while(dir_element = readdir(dir_p)){

        lstat(dir_element->d_name, &file_info);          //getting a file stats

        puts(dir_element->d_name);                       // show current filename
        printf("file mode: %d\n", file_info.st_mode);

        // print what kind of file we are dealing with
        if (file_info.st_mode == S_IFDIR) puts("|| directory");
        if (file_info.st_mode == S_IFREG) puts("|| regular file");
        if (file_info.st_mode == S_IFLNK) puts("|| symbolic link");
    }

}

Ответы [ 3 ]

4 голосов
/ 06 октября 2011

Существует набор макросов для интерпретации st_mode, который является более сложным, чем вы думаете.Используйте их вместо непосредственного исследования поля:

if (S_ISREG(file_info.st_mode))
    // file is a regular file
else if (S_ISLNK(file_info.st_mode))
    // ...

Также есть S_ISDIR, S_ISSOCK и еще несколько.См., Например, здесь для информации.

3 голосов
/ 14 марта 2016

Я знаю, что это годы спустя, но для потомков вы делали это неправильно:
@ alk был прав, поле st_mode содержит больше информации, например, тип файла, права доступа к файлу,etc
Чтобы извлечь тип файла, вы выполняете его поразрядно, в поле st_mode и маске типа файла S_IFMT . Затем проверьте результат на то, что вам нужно.Вот что делают макросы, упомянутые @ Ernest Friedman-Hill .Swicth лучше подходит для комплексной проверки, например

для простого случая:

     if ((file_info.st_mode & S_IFMT)==S_IFDIR) puts("|| directory");

для комплексной проверки:

       struct stat st;
       ...

      switch (st.st_mode & S_IFMT) {
        case S_IFREG:  
            puts("|| regular file");
            break;
        case S_IFDIR:
            puts("|| directory");
            break;
        case S_IFCHR:        
            puts("|| character device");
            break;
        case S_IFBLK:        
            puts("|| block device");
            break;
        case S_IFLNK: 
            puts("|| symbolic link");
            break;
        case S_IFIFO: 
            puts("|| pipe");    
            break;
        case S_IFSOCK:
            puts("|| socket");
            break;
        default:
            puts("|| unknown"); 
     }
2 голосов
/ 06 октября 2011

Режим несет много информации.

Попробуйте следующий тип теста:

if (S_ISDIR(file_info.st_mode))  puts("|| directory");
...