Подтвердить что ты не робот

С++ - определение того, существует ли каталог (а не файл) в Linux

Как определить, существует ли каталог (а не файл) с использованием С++ в Linux? Я попытался использовать функцию stat(), но он вернулся положительно, когда файл был найден. Я только хочу узнать, является ли введенная строка каталогом, а не чем-то еще.

4b9b3361

Ответ 1

В соответствии с man (2) stat вы можете использовать макрос S_ISDIR в поле st_mode:

bool isdir = S_ISDIR(st.st_mode);

Заметьте, я бы рекомендовал использовать Boost и/или Qt4, чтобы упростить кросс-платформенную поддержку, если ваше программное обеспечение может быть жизнеспособным на других ОС.

Ответ 2

как насчет того, что я нашел здесь

#include <dirent.h>

bool DirectoryExists( const char* pzPath )
{
    if ( pzPath == NULL) return false;

    DIR *pDir;
    bool bExists = false;

    pDir = opendir (pzPath);

    if (pDir != NULL)
    {
        bExists = true;    
        (void) closedir (pDir);
    }

    return bExists;
}

Или используя stat

struct stat st;
if(stat("/tmp",&st) == 0)
    if(st.st_mode & S_IFDIR != 0)
        printf(" /tmp is present\n");

Ответ 3

Если вы можете проверить увеличить библиотеку файловой системы. Это отличный способ справиться с такими проблемами в общем и переносном режиме.

В этом случае было бы достаточно использовать:

#include "boost/filesystem.hpp"   
using namespace boost::filesystem; 
...
if ( !exists( "test/mydir" ) ) {bla bla}

Ответ 4

То, как я понимаю ваш вопрос, таков: у вас есть путь, скажем, /foo/bar/baz (baz - файл), и вы хотите знать, существует ли /foo/bar. Если это так, решение выглядит примерно так (непроверено):

char *myDir = dirname(myPath);
struct stat myStat;
if ((stat(myDir, &myStat) == 0) && (((myStat.st_mode) & S_IFMT) == S_IFDIR)) {
    // myDir exists and is a directory.
}

Ответ 5

Если вы хотите узнать, существует ли каталог, потому что вы хотите что-то сделать с ним, если это так (создайте файл/каталог внутри, сканируйте его содержимое и т.д.), вы должны просто пойти и сделать то, что вы хотите сделать, затем проверьте, не сработало ли оно, и если да, сообщите пользователю strerror(errno) пользователю. Это общий принцип программирования под Unix: не пытайтесь выяснить, будет ли то, что вы хотите сделать, будет работать. Попытайтесь, а затем посмотрите, не сработало ли оно.

Если вы хотите вести себя специально, если что-то не удалось, потому что каталог не существует (например, если вы хотите создать файл и все необходимые каталоги), вы можете проверить errno == ENOENT после open выходит из строя.

Я вижу, что один из респондентов рекомендовал использовать boost::filesystem. Я бы хотел одобрить эту рекомендацию, но, к сожалению, я не могу, потому что boost::filesystem не только для заголовка, а для всех модулей Boost, отличных от заголовков, есть ужасная запись, вызывающая таинственный поломка, если вы обновляете общую библиотеку без перекомпиляции приложение, или даже если вам просто не удалось скомпилировать приложение с точно такими же флагами, которые использовались для компиляции разделяемой библиотеки. Удержание гонения просто не стоит.

Ответ 6

С С++ 17 вы можете использовать std::filesystem, в С++ 14 std::experimental::filesystem уже доступно. Оба позволяют использовать filesystem::is_directory().

С++ 17:

#include <filesystem>
std::filesystem::path myDirectory = "my/directory/path";
if (std::filesystem::path::is_directory(myDirectory)) {
    if (std::filesystem::path::exists(myDirectory)) {
        // Process existing directory.
    }
}

С++ 14:

#include <experimental/filesystem>
std::experimental::filesystem::path myDirectory = "my/directory/path";
if (std::experimental::filesystem::path::is_directory(myDirectory)) {
    if (std::experimental::filesystem::path::exists(myDirectory)) {
        // Process existing directory.
    }
}   

Примечание: Обе функции перебрасывают filesystem_error в случае ошибок. Если вы хотите избежать перехвата исключений, используйте перегруженные варианты с std::error_code в качестве второго параметра. Например.

std::error_code errorCode;
bool error = false;
std::filesystem::path myDirectory = "my/directory/path";
if (std::filesystem::path::is_directory(myDirectory, errorCode)) {
    if (std::filesystem::path::exists(myDirectory, errorCode)) {
        // Process existing directory.
    }
    else {
        error = true;
    }
}
else {
    error = true;
}

if (error) {
    std::cout << errorCode.message() << std::endl;
}