C++ - 确定Linux中是否存在目录(不是文件)

发布于 2024-10-17 09:48:42 字数 95 浏览 2 评论 0原文

在 Linux 中使用 C++ 如何确定目录(而不是文件)是否存在?我尝试使用 stat() 函数,但当找到文件时它返回正值。我只想查找输入的字符串是否是目录,而不是其他内容。

How would I determine if a directory (not a file) existed using C++ in Linux? I tried using the stat() function but it returned positive when a file was found. I only want to find if the inputted string is a directory, not something else.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

夏末染殇 2024-10-24 09:48:42

根据 man(2) stat 您可以在 st_mode 字段上使用 S_ISDIR 宏:

bool isdir = S_ISDIR(st.st_mode);

旁注,我建议如果您的软件可以在其他操作系统上运行,则使用 Boost 和/或 Qt4 可以更轻松地实现跨平台支持。

According to man(2) stat you can use the S_ISDIR macro on the st_mode field:

bool isdir = S_ISDIR(st.st_mode);

Side note, I would recommend using Boost and/or Qt4 to make cross-platform support easier if your software can be viable on other OSs.

我ぃ本無心為│何有愛 2024-10-24 09:48:42

我在这里找到的东西怎么样

#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");

how about something i found here

#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;
}

Or using stat

struct stat st;
if(stat("/tmp",&st) == 0)
    if(st.st_mode & S_IFDIR != 0)
        printf(" /tmp is present\n");
邮友 2024-10-24 09:48:42

如果您可以查看 boost 文件系统库。这是以通用且可移植的方式处理此类问题的好方法。

在这种情况下,使用以下内容就足够了:

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

If you can check out the boost filesystem library. It's a great way to deal with this kind of problems in a generic and portable manner.

In this case it would suffice to use:

#include "boost/filesystem.hpp"   
using namespace boost::filesystem; 
...
if ( !exists( "test/mydir" ) ) {bla bla}
很快妥协 2024-10-24 09:48:42

我理解你的问题的方式是这样的:你有一个路径,例如 /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.
}

The way I understand your question is this: you have a path, say, /foo/bar/baz (baz is a file) and you want to know whether /foo/bar exists. If so, the solution looks something like this (untested):

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.
}
り繁华旳梦境 2024-10-24 09:48:42

在 C++17** 中,std::filesystem提供了两种变体来确定路径是否存在:

  1. is_directory() 确定路径是否是目录并且确实存在于实际文件系统中
  2. exists() 只是确定路径是否存在于实际文件系统中(不检查它是否是目录)

示例(没有错误处理):

#include <iostream>
#include <filesystem> // C++17
//#include <experimental/filesystem> // C++14
namespace fs = std::filesystem;
//namespace fs = std::experimental::filesystem; // C++14

int main()
{
    // Prepare.
    const auto processWorkingDir = fs::current_path();
    const auto existingDir = processWorkingDir / "existing/directory"; // Should exist in file system.
    const auto notExistingDir = processWorkingDir / "fake/path";
    const auto file = processWorkingDir / "file.ext"; // Should exist in file system.

    // Test.
    std::cout
        << "existing dir:\t" << fs::is_directory(existingDir) << "\n"
        << "fake dir:\t" << fs::is_directory(notExistingDir) << "\n"
        << "existing file:\t" << fs::is_directory(file) << "\n\n";

    std::cout
        << "existing dir:\t" << fs::exists(existingDir) << "\n"
        << "fake dir:\t" << fs::exists(notExistingDir) << "\n"
        << "existing file:\t" << fs::exists(file);
}

可能的输出:

existing dir:   1
fake dir:       0
existing file:  0

existing dir:   1
fake dir:       0
existing file:  1

**在 C++14 中 可用


std::experimental::filesystem两者均 如果出现错误,函数会抛出 filesystem_error 。如果您想避免捕获异常,请使用 std::error_code< 的重载变体/code>作为第二个参数。

#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;

bool isExistingDir(const fs::path& p) noexcept
{
    try
    {
        return fs::is_directory(p);
    }
    catch (std::exception& e)
    {
        // Output the error message.
        const auto theError = std::string{ e.what() };
        std::cerr << theError;

        return false;
    }
}

bool isExistingDirEC(const fs::path& p) noexcept
{
    std::error_code ec;
    const auto isDir = fs::is_directory(p, ec);
    if (ec)
    {
        // Output the error message.
        const auto theError = ec.message();
        std::cerr << theError;

        return false;
    }
    else
    {
        return isDir;
    }
}

int main()
{
    const auto notExistingPath = fs::path{ "\xa0\xa1" };
    isExistingDir(notExistingPath);
    isExistingDirEC(notExistingPath);
}

In C++17**, std::filesystem provides two variants to determine the existence of a path:

  1. is_directory() determines, if a path is a directory and does exist in the actual filesystem
  2. exists() just determines, if the path exists in the actual filesystem (not checking, if it is a directory)

Example (without error handling):

#include <iostream>
#include <filesystem> // C++17
//#include <experimental/filesystem> // C++14
namespace fs = std::filesystem;
//namespace fs = std::experimental::filesystem; // C++14

int main()
{
    // Prepare.
    const auto processWorkingDir = fs::current_path();
    const auto existingDir = processWorkingDir / "existing/directory"; // Should exist in file system.
    const auto notExistingDir = processWorkingDir / "fake/path";
    const auto file = processWorkingDir / "file.ext"; // Should exist in file system.

    // Test.
    std::cout
        << "existing dir:\t" << fs::is_directory(existingDir) << "\n"
        << "fake dir:\t" << fs::is_directory(notExistingDir) << "\n"
        << "existing file:\t" << fs::is_directory(file) << "\n\n";

    std::cout
        << "existing dir:\t" << fs::exists(existingDir) << "\n"
        << "fake dir:\t" << fs::exists(notExistingDir) << "\n"
        << "existing file:\t" << fs::exists(file);
}

Possible output:

existing dir:   1
fake dir:       0
existing file:  0

existing dir:   1
fake dir:       0
existing file:  1

**in C++14 std::experimental::filesystem is available


Both functions throw filesystem_error in case of errors. If you want to avoid catching exceptions, use the overloaded variants with std::error_code as second parameter.

#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;

bool isExistingDir(const fs::path& p) noexcept
{
    try
    {
        return fs::is_directory(p);
    }
    catch (std::exception& e)
    {
        // Output the error message.
        const auto theError = std::string{ e.what() };
        std::cerr << theError;

        return false;
    }
}

bool isExistingDirEC(const fs::path& p) noexcept
{
    std::error_code ec;
    const auto isDir = fs::is_directory(p, ec);
    if (ec)
    {
        // Output the error message.
        const auto theError = ec.message();
        std::cerr << theError;

        return false;
    }
    else
    {
        return isDir;
    }
}

int main()
{
    const auto notExistingPath = fs::path{ "\xa0\xa1" };
    isExistingDir(notExistingPath);
    isExistingDirEC(notExistingPath);
}
走野 2024-10-24 09:48:42

如果你想知道一个目录是否存在,因为你想用它做一些事情(在里面创建一个文件/目录,扫描它的内容等),你应该继续做任何你想做的事情,然后检查是否失败,如果失败,则向用户报告 strerror(errno)。这是 Unix 下编程的一般原则:不要试图弄清楚你想做的事情是否会起作用。尝试一下,然后看看是否失败。

如果您想在因目录不存在而导致失败时采取特殊措施(例如,如果您想创建一个文件和所有必需的包含目录),请检查 errno == ENOENT open 失败后。

我看到一位响应者建议使用 boost::filesystem。我愿意赞同这个建议,但遗憾的是我不能,因为 boost::filesystem 不是仅限标头的,并且 Boost 的所有非仅限标头的模块都有一个如果您升级共享库而不重新编译应用程序,或者即使您只是没有设法使用与编译共享库所用的完全相同相同的标志来编译应用程序,那么会导致神秘损坏的可怕记录。维护的痛苦是不值得的。

If you want to find out whether a directory exists because you want to do something with it if it does (create a file/directory inside, scan its contents, etc) you should just go ahead and do whatever you want to do, then check whether it failed, and if so, report strerror(errno) to the user. This is a general principle of programming under Unix: don't try to figure out whether the thing you want to do will work. Attempt it, then see if it failed.

If you want to behave specially if whatever-it-was failed because a directory didn't exist (for instance, if you want to create a file and all necessary containing directories) you check for errno == ENOENT after open fails.

I see that one responder has recommended the use of boost::filesystem. I would like to endorse this recommendation, but sadly I cannot, because boost::filesystem is not header-only, and all of Boost's non-header-only modules have a horrible track record of causing mysterious breakage if you upgrade the shared library without recompiling the app, or even if you just didn't manage to compile your app with exactly the same flags used to compile the shared library. The maintenance grief is just not worth it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文