web-dev-qa-db-ja.com

C ++-Linuxにディレクトリ(ファイルではない)が存在するかどうかの判別

LinuxでC++を使用して(ファイルではなく)ディレクトリが存在するかどうかをどのように判断しますか? stat()関数を使用しようとしましたが、ファイルが見つかったときに肯定的な結果を返しました。入力した文字列がディレクトリであり、他の文字列ではない場合にのみ検索したい。

23
MetaDark

man(2)stat に従って、st_modeフィールドでS_ISDIRマクロを使用できます。

bool isdir = S_ISDIR(st.st_mode);

補足として、他のOSでソフトウェアを実行できる場合は、BoostやQt4を使用してクロスプラットフォームサポートを容易にすることをお勧めします。

29
OneOfOne

私が見つけたものはどうですか ここ

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

boost filesystem library をチェックアウトできる場合。この種の問題を一般的で移植可能な方法で処理するのに最適な方法です。

この場合、以下を使用するだけで十分です。

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

私があなたの質問を理解する方法はこれです:あなたにはパスがあります、たとえば、/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.
}
6
DarkDust

ディレクトリ(ファイル/ディレクトリの作成、その内容のスキャンなど)で何かをしたいので、ディレクトリが存在するかどうかを知りたい場合は、先に進み、やりたいことをしてください失敗したかどうか、失敗した場合は、strerror(errno)をユーザーに報告します。これはUnixでのプログラミングの一般的な原則です。やりたいことがうまくいくかどうかを理解しようとしないでください。試してみて、失敗したかどうかを確認します。

ディレクトリが存在しなかったために何が失敗しても特別な動作をする場合(たとえば、ファイルと必要なすべてのディレクトリを作成する場合)、errno == ENOENTopenが失敗した後。

1人のレスポンダーがboost::filesystem。私はlikeを推奨しますが、残念ながらboost::filesystemはヘッダー専用ではなく、Boostの非ヘッダー専用モジュールはすべて、アプリを再コンパイルせずに共有ライブラリをアップグレードした場合、またはコンパイルできなかった場合でも、不可解な破損を引き起こすという恐ろしい実績があります。 exactlyで共有ライブラリをコンパイルするために使用されるものと同じフラグ。メンテナンスの悲しみはそれだけの価値はありません。

1
zwol

C++ 17 **では、 _std::filesystem_ は、パスの存在を判断する2つのバリアントを提供します。

  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_ をスローします。例外のキャッチを回避する場合は、2番目のパラメーターとして _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);
}
_
1
Roi Danton