How can I tell if a given path is a directory or a file? (C/C++)
Asked Answered
B

9

56

I'm using C and sometimes I have to handle paths like

  • C:\Whatever
  • C:\Whatever\
  • C:\Whatever\Somefile

Is there a way to check if a given path is a directory or a given path is a file?

Brisson answered 28/9, 2008 at 22:42 Comment(0)
A
36

Call GetFileAttributes, and check for the FILE_ATTRIBUTE_DIRECTORY attribute.

Actinolite answered 28/9, 2008 at 22:47 Comment(1)
If you need to support Windows 98, then you can't use this function. See my answer about PathIsDirectory below if you need Win98 support.Aili
T
128

stat() will tell you this.

struct stat s;
if( stat(path,&s) == 0 )
{
    if( s.st_mode & S_IFDIR )
    {
        // it's a directory
    }
    else if( s.st_mode & S_IFREG )
    {
        // it's a file
    }
    else
    {
        // something else
    }
}
else
{
    // error
}
Toffic answered 28/9, 2008 at 22:50 Comment(6)
the only problem I have with this code is the comment in the else case. Just because something isn't a directory doesn't mean it's a file.Leake
@dicroce: Yep, true enough; fixed.Toffic
when I try to use this, I got "aggregate ‘main(int, char**)::stat s’ has incomplete type and cannot be defined" and really could not get what is the error. It gives error first in the line of struct stat s; What could be my mistake?Shirashirah
Okay, I needed to add #include <sys/stat.h> my bad :)Shirashirah
is there an overload or similar function that support wide character path?Dukie
What will happen if the path is a symbolic link to a directory?Dromedary
C
37

With C++14/C++17 you can use the platform independent is_directory() and is_regular_file() from the filesystem library.

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

int main()
{
    const std::string pathString = "/my/path";
    const fs::path path(pathString); // Constructing the path from a string is possible.
    std::error_code ec; // For using the non-throwing overloads of functions below.
    if (fs::is_directory(path, ec))
    { 
        // Process a directory.
    }
    if (ec) // Optional handling of possible errors.
    {
        std::cerr << "Error in is_directory: " << ec.message();
    }
    if (fs::is_regular_file(path, ec))
    {
        // Process a regular file.
    }
    if (ec) // Optional handling of possible errors. Usage of the same ec object works since fs functions are calling ec.clear() if no errors occur.
    {
        std::cerr << "Error in is_regular_file: " << ec.message();
    }
}

In C++14 use std::experimental::filesystem.

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

Additional implemented checks are listed in section "File types".

Commission answered 7/4, 2017 at 15:4 Comment(2)
Hi @Roi Danton, thanks for your answer. Do you know why this doesn't work on macOS? It seems that it's related to Clang not supporting this library. Very unfortunate, IMO.Thrombosis
@Thrombosis Clang supports std::filesystem.Make sure to use Clang 7 or later with option -std=c++17. Minimal example at compiler explorer.Commission
A
36

Call GetFileAttributes, and check for the FILE_ATTRIBUTE_DIRECTORY attribute.

Actinolite answered 28/9, 2008 at 22:47 Comment(1)
If you need to support Windows 98, then you can't use this function. See my answer about PathIsDirectory below if you need Win98 support.Aili
A
14

In Win32, I usually use PathIsDirectory and its sister functions. This works in Windows 98, which GetFileAttributes does not (according to the MSDN documentation.)

Aili answered 28/9, 2008 at 22:56 Comment(2)
I haven't tried it but the earliest documented version was distributed with Windows 95, so probably not.Aili
You can certainly use GetFileAttributes() in Windows 98, and AFAIK it predates the existence of PathIsDirectory(). You can't rely on MSDN documentation when checking the minimum OS requirement of an API because MSDN lies! When MS drops support for an OS version, they like to remove most references to it from MSDN documentation, especially in minimum OS requirements of existing APIs.Questionless
E
2

On Windows you can use GetFileAttributes on an open handle.

Eldrida answered 28/9, 2008 at 22:46 Comment(0)
B
0

This is a simple method using the GetFileAttributesW function to check if the path is a directory on Windows. If the received path must be a directory or a file path then if it is not a directory path you can assume that it is a file path.

bool IsDirectory(std::wstring path)
{
    DWORD attrib = GetFileAttributes(path.c_str());

    if ((attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)
        return true;

    return false;
}
Bolden answered 5/1, 2021 at 20:58 Comment(0)
D
0

A refinement of @MikeF answer:

You need the stat() library function, which characterizes a file for you; but - this is not sufficient, since you may have received a path which is a symbolic link to a directory - and users / shells will think of that as an actual directory, though stat does not. So, you have to walk the path. Here's how:

following symbolic links in C

combining those two, here is a function you could use:

#include <stdlib.h>
#include <sys/stat.h>
#include <stdbool.h>

// Returns true if the relevant library calls succeeded (in
// which case  `*result` holds a valid value)
static bool is_directory(bool* result, char const *path)
{
    char * real_path = realpath(path, NULL);
    if (real_path == NULL) { return false; }
    struct stat s;
    if (stat(real_path, &s) != 0) { return false; }
    *result = (s.st_mode & S_IFDIR);
    return true;
}
Dromedary answered 10/9, 2024 at 15:48 Comment(0)
M
-2

If you're using CFile you can try

CFileStatus status;
    if (CFile::GetStatus(fileName, status) && status.m_attribute == 0x10){
       //it's directory
}
Mulder answered 14/9, 2015 at 11:49 Comment(0)
S
-6

Easier to try FileInfo.isDir() in qt

Shine answered 23/8, 2013 at 14:2 Comment(3)
Could you explain why to use a GUI library when a file system access is in question?Zest
Thanks, that's exactly what I was looking for. (Via Google.)Patchwork
why on earth did you 'drag' qt along here?Darden

© 2022 - 2025 — McMap. All rights reserved.