Различение файлов и папок на общем диске в Linux

Я пытаюсь перечислить все файлы в определенном каталоге на общем диске, используя следующий код:

#include <iostream>
#include <string>

#include "dirent.h"

int main ()
{
    DIR *directoryHandle = opendir("./temp/");
    if (NULL != directoryHandle)
    {
        dirent *entry = readdir(directoryHandle);
        while (NULL != entry)
        {
            //skip directories and select only files (hopefully)
            if ((DT_DIR != entry->d_type) && (DT_REG == entry->d_type || DT_UNKNOWN == entry->d_type))
            {
                std::cout << "Name: " << entry->d_name << " Type:" << std::to_string(entry->d_type) << std::endl;
            }

            //go to next entry
            entry = readdir(directoryHandle);
        }
        closedir(directoryHandle);
    }

    return 0;
}

Проблема в том, что entry->d_type содержит DT_UNKNOWN как для каталогов, так и для файлов в каталоге ./temp/.

Есть ли какой-либо (надежный) специфический для Linux способ попытаться прочитать каждую запись и определить, является ли она файлом или каталогом?

Вывод cat /etc/SuSE-release:

SUSE Linux Enterprise Desktop 11 (x86_64) ВЕРСИЯ = 11 PATCHLEVEL = 1

Версия для Linux: 2.6.32.59-0.7-по умолчанию.

Тем не менее, я ожидаю, что этот код будет работать и на других платформах.


person Mihai Todor    schedule 11.09.2012    source источник
comment
Что здесь означает общий диск? smb, nfs, sshfs и т. д.? о, и вы путаете версию ядра с версией дистрибутива.   -  person PlasmaHH    schedule 11.09.2012
comment
Упс... У меня нет такого опыта работы с системой Linux. Выход df -T указывает nfs4 для этого диска.   -  person Mihai Todor    schedule 11.09.2012


Ответы (5)


Используйте 1_. Вы получите struct stat с полем st_mode и макросами S_ISDIR/S_ISREG:

isDirectory = S_ISDIR(statBuf.st_mode);
isFile = S_ISREG(statBuf.st_mode);

См. man 2 stat. Включите sys/stat.h.

person pb2q    schedule 11.09.2012

Если вы получаете DT_UNKNOWN, вам придется позвонить lstat() и проверить поле st_mode, чтобы определить если это файл, каталог или символическая ссылка. Если вам не нужны символические ссылки, используйте вместо них stat().

person Hasturkun    schedule 11.09.2012

Существует библиотека для файловой системы, в которой есть команда is_directory. Использование такой библиотеки, безусловно, заставит код работать и на других платформах, но я не уверен, что это сработает для вашей конкретной проблемы.

person denahiro    schedule 11.09.2012
comment
На данный момент я предпочитаю не создавать зависимость от boost::filesystem... - person Mihai Todor; 11.09.2012
comment
+1 для Boost::FS, это отличная библиотека, и ее гораздо проще использовать, чем dirent.h. - person Fred Foo; 11.09.2012
comment
@MihaiTodor Ну, это выбор дизайна, и это ваш дизайн, вот и все. Я думаю, что иногда я немного счастлив, когда включаю библиотеки повышения. - person denahiro; 11.09.2012

Попробуйте это. В нем перечислены файлы в каталоге за вычетом папок:

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

DIR           *d;
struct dirent *dir;
struct stat s;
d = opendir("./temp/");

if (d)
{
  while ((dir = readdir(d)))
  {
    if (stat(dir->d_name,&s) != 0) {
        /* is this a regular file? */
        if ((s.st_mode & S_IFMT) == S_IFREG)
            printf("%s\n", dir->d_name);

    }
  }
  closedir(d);
}
person Software_Designer    schedule 11.09.2012

person    schedule
comment
Итак, чем это отличается от моего кода? DT_DIR определяется как 0x4... - person Mihai Todor; 29.01.2014