2010-04-05 2 views
3

Я пытаюсь проверить, есть ли в папке какие-либо подпапки, без итерации через свои дочерние элементы в Linux. Самое близкое, что я нашел до сих пор, это использование ftw и остановка в первой подпапке - или с использованием scandir и фильтрация результатов. Оба, однако, являются излишним для моих целей, я просто хочу да/нет.Проверка наличия подпапок Linux

В Windows это делается путем вызова SHGetFileInfo, а затем тестирования dwAttributes & SFGAO_HASSUBFOLDER по возвращенной структуре. Есть ли такой вариант в Linux?

+0

ли вы на самом деле смотрели на реализацию SHGetFileInfo на Windows? Разве это не просто итерация записей в каталоге? – MarkR

ответ

4

Стандартным ответом является вызов stat в каталог, затем отметьте поле st_nlink («количество жестких ссылок»). В стандартной файловой системе , каждый каталог, как гарантируется, имеет две жесткие ссылки (. и ссылку из родительского каталога в текущий каталог), поэтому каждая жесткая ссылка за пределами 2 указывает подкаталог (в частности, ссылка на каталог .. подкаталога на текущий каталог).

Однако, я понимаю, что файловые системы не требуются для реализации этого (см., Например, this mailing list posting), поэтому он не гарантированно работает.

В противном случае, вы должны сделать, как вы делаете:

  1. перебрать содержимого каталога с помощью glob с GNU специфичной GLOB_ONLYDIR флагом, или scandir или readdir.
  2. Позвоните по номеру stat по каждому результату и проверьте S_ISDIR(s.st_mode), чтобы убедиться, что найденные файлы являются каталогами. Или, необязательно, отметьте struct dirent.d_type: если это DT_DIR, тогда это файл, и если это DT_UNKNOWN, вам придется его ставить.
+0

+1, но '..' не является ссылкой на данный каталог; это ссылка на родителя. Однако его взаимность является одной из двух. – Potatoswatter

+0

'struct dirent.d_type', хотя« не поддерживается всеми типами файловых систем », устраняет необходимость' stat (2) ' – wRAR

+0

@Potatocorn, @wRAR - я обновил свой ответ. Благодарю. –

0

getdirentries действительно хотите, чтобы вы этого хотели? Я думаю, что shoudl ничего не возвращает, если нет каталогов. Я бы пробовал это сам, но временно не имел доступа к ящику linux :(

+0

Это, конечно же, возвращает subdirs AND файлы. Кроме того, «СООТВЕТСТВИЕ К Не в POSIX.1-2001. Присутствуйте на BSD и в нескольких других системах. Вместо этого используйте opendir (3) и readdir (3)». И фильтрация вывода 'readdir (3)' является единственным способом, поскольку флаг «не имеет подкаталогов» не существует. – wRAR

2

Возможности, о которых вы упомянули (а также e.James), мне кажутся такими, что они лучше подходят для сценария оболочки, чем программа на C++. Предположив на «C++» тег был намеренным, я думаю, вы, вероятно, будет лучше использовать POSIX API напрямую:

// warning: untested code. 
bool has_subdir(char const *dir) { 
    std::string dot("."), dotdot(".."); 
    bool found_subdir = false;  
    DIR *directory; 

    if (NULL == (directory = opendir(dir))) 
     return false; 

    struct dirent *entry; 
    while (!found_subdir && ((entry = readdir(directory)) != NULL)) { 
     if (entry->d_name != dot && entry->d_name != dotdot) { 
      struct stat status; 
      stat(entry->d_name, &status); 
      found_subdir = S_ISDIR(status.st_mode); 
     } 
    } 
    closedir(directory); 
    return found_subdir; 
} 
+0

Если вы хотите оптимизировать '' '' '' '' '' '' '' путем подъема из цикла, вы можете также сделать их 'static' тоже. – Potatoswatter

+0

Тег C++ был преднамеренным, хотя и неправильным. Я обновлю его, так что это актуально. – laura

+0

@Potatocorn: Хорошая точка - на самом деле, это не помешает сделать их 'static const'. –