检查目录是否存在的可移植方法[ Windows/Linux,C ]

我想检查给定的目录是否存在。我知道如何在 Windows 上做到这一点:

BOOL DirectoryExists(LPCTSTR szPath)
{
DWORD dwAttrib = GetFileAttributes(szPath);


return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}

和 Linux:

DIR* dir = opendir("mydir");
if (dir)
{
/* Directory exists. */
closedir(dir);
}
else if (ENOENT == errno)
{
/* Directory does not exist. */
}
else
{
/* opendir() failed for some other reason. */
}

But I need a portable way of doing this .. Is there any way to check if a directory exists no matter what OS Im using? Maybe C standard library way?

我知道我可以使用预处理器指令并在不同的操作系统上调用这些函数,但这不是我要求的解决方案。

我最终得到了这个,至少现在是这样:

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>


int dirExists(const char *path)
{
struct stat info;


if(stat( path, &info ) != 0)
return 0;
else if(info.st_mode & S_IFDIR)
return 1;
else
return 0;
}


int main(int argc, char **argv)
{
const char *path = "./TEST/";
printf("%d\n", dirExists(path));
return 0;
}
131941 次浏览

Use boost::filesystem, that will give you a portable way of doing those kinds of things and abstract away all ugly details for you.

You can use the GTK glib to abstract from OS stuff.

glib provides a g_dir_open() function which should do the trick.

stat() works on Linux., UNIX and Windows as well:

#include <sys/types.h>
#include <sys/stat.h>


struct stat info;


if( stat( pathname, &info ) != 0 )
printf( "cannot access %s\n", pathname );
else if( info.st_mode & S_IFDIR )  // S_ISDIR() doesn't exist on my windows
printf( "%s is a directory\n", pathname );
else
printf( "%s is no directory\n", pathname );

Since I found that the above approved answer lacks some clarity and the op provides an incorrect solution that he/she will use. I therefore hope that the below example will help others. The solution is more or less portable as well.

/******************************************************************************
* Checks to see if a directory exists. Note: This method only checks the
* existence of the full path AND if path leaf is a dir.
*
* @return  >0 if dir exists AND is a dir,
*           0 if dir does not exist OR exists but not a dir,
*          <0 if an error occurred (errno is also set)
*****************************************************************************/
int dirExists(const char* const path)
{
struct stat info;


int statRC = stat( path, &info );
if( statRC != 0 )
{
if (errno == ENOENT)  { return 0; } // something along the path does not exist
if (errno == ENOTDIR) { return 0; } // something in path prefix is not a dir
return -1;
}


return ( info.st_mode & S_IFDIR ) ? 1 : 0;
}

With C++17 you can use std::filesystem::is_directory function (https://en.cppreference.com/w/cpp/filesystem/is_directory). It accepts a std::filesystem::path object which can be constructed with a unicode path.

The above examples does not use [_access]1 which can be used for both Windows and Linux. Code sample (Windows) to test with [stat]2, _access() and latest filesystem's [exists]3.

#include <iostream>
#include <Windows.h>
#include <io.h>
#include <filesystem>
#include <vector>
#include <string>


using namespace std;
namespace fs = std::filesystem;
std::vector<std::string> DirPaths
{
"G:\\My-Shcool-2021-22",
"\\\\192.168.111.8\\Oaco\\RotData\\VV-VA",
"\\\\192.168.111.15\\5500\\C-drive\\Oaco\\RotateEarthProject",   "\\\\192.168.111.18\\d$\\Mercurial\\Workspace\\HideMoon\\Win32\\Debug",
"Z:\\SuperSaver" //mapped network drive; symbolic link
};
/* test if the path is a directory
*/
void TestDirExists ()
{
int erno =-1;
struct stat  info {};
auto ErrorMsg = [&](std::string path)
{
_get_errno(&erno);
if (erno == EACCES)
cout << "access denied  " << path << endl;
else if (erno == ENOENT)
cout << "dir path not found  " << path << endl;
else if (erno == EINVAL)
cout << "invalid parameter  " << path << endl;
};


for (const auto &dp : DirPaths)
{
erno = -1;
if (stat(dp.c_str(), &info) != 0)
ErrorMsg(dp);
if (_access(dp.c_str(), 0) != 0)
ErrorMsg(dp);
if (fs::exists(dp)==0)
ErrorMsg(dp);
if(erno < 0)
cout << "#Dir Found: " << dp << endl;
}

} [1]: https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/access-waccess?view=msvc-170 [2]: https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/stat-functions?view=msvc-170 [3]: https://en.cppreference.com/w/cpp/filesystem/exists