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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4980815/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 00:19:17  来源:igfitidea点击:

C++ - Determining if directory (not a file) exists in Linux

c++linuxdirectoryexists

提问by MetaDark

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.

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

采纳答案by OneOfOne

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

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

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.

旁注,如果您的软件可以在其他操作系统上运行,我建议使用 Boost 和/或 Qt4 来简化跨平台支持。

回答by ayush

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

回答by DarkDust

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/barexists. If so, the solution looks something like this (untested):

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

回答by Dr G

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.

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

In this case it would suffice to use:

在这种情况下,使用:

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

回答by zwol

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.

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

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 == ENOENTafter openfails.

如果由于目录不存在(例如,如果您想创建一个文件和所有必需的包含目录)而导致任何结果失败,如果您想采取特殊的行为,则errno == ENOENTopen失败后检查。

I see that one responder has recommended the use of boost::filesystem. I would liketo endorse this recommendation, but sadly I cannot, because boost::filesystemis 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 exactlythe same flags used to compile the shared library. The maintenance grief is just not worth it.

我看到一位响应者建议使用boost::filesystem. 我会喜欢赞同这一建议,但遗憾的是我不能,因为boost::filesystem不是头只,和所有的Boost的非仅标头模块都有,如果你不需要重新编译应用程序升级共享库造成神秘破裂的可怕的记录,或者即使您只是没有设法使用用于编译共享库的完全相同的标志来编译您的应用程序。维修方面的痛苦是不值得的。

回答by Roi Danton

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

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

  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)
  1. is_directory()确定路径是否是目录并且确实存在于实际文件系统中
  2. exists()只是确定路径是否存在于实际文件系统中(不检查,如果它是一个目录)

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::filesystemis available

**在 C++14std::experimental::filesystem中可用



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

filesystem_error如果出现错误,这两个函数都会抛出。如果您想避免捕获异常,请使用重载的变体std::error_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);
}