Проверка наличия подпапок linux - PullRequest
3 голосов
/ 05 апреля 2010

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

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

Ответы [ 3 ]

4 голосов
/ 05 апреля 2010

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

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

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

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

Упомянутые вами возможности (а также возможности 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 голосов
/ 05 апреля 2010

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

...