53

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?

Kirill Kobelev
  • 10,252
  • 6
  • 30
  • 51
DylanJ
  • 2,373
  • 3
  • 25
  • 24

8 Answers8

126

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
}
Filip Müller
  • 1,096
  • 5
  • 18
  • 4
    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. – dicroce Sep 28 '08 at 23:27
  • @dicroce: Yep, true enough; fixed. –  Sep 29 '08 at 00:54
  • 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? – meakgoz Mar 30 '15 at 13:40
  • 4
    Okay, I needed to add #include my bad :) – meakgoz Mar 30 '15 at 13:54
  • is there an overload or similar function that support wide character path? – mbaros Jul 31 '16 at 19:25
35

Call GetFileAttributes, and check for the FILE_ATTRIBUTE_DIRECTORY attribute.

Colen
  • 13,428
  • 21
  • 78
  • 107
  • 3
    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. – jeffm Sep 28 '08 at 23:29
33

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".

Roi Danton
  • 7,933
  • 6
  • 68
  • 80
  • 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. – mannyglover Nov 13 '18 at 16:15
  • 1
    @mannyglover Clang supports `std::filesystem`.Make sure to use Clang 7 or later with option `-std=c++17`. [Minimal example at compiler explorer](https://godbolt.org/z/iCjzPZ). – Roi Danton Nov 13 '18 at 19:01
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.)

jeffm
  • 3,120
  • 1
  • 34
  • 57
  • 1
    I haven't tried it but the earliest documented version was distributed with Windows 95, so probably not. – jeffm May 05 '14 at 01:48
  • 5
    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. – Remy Lebeau Aug 02 '16 at 20:54
2

On Windows you can use GetFileAttributes on an open handle.

Scott
  • 766
  • 7
  • 20
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;
}
Juan Carlos
  • 131
  • 1
  • 6
-2

If you're using CFile you can try

CFileStatus status;
    if (CFile::GetStatus(fileName, status) && status.m_attribute == 0x10){
       //it's directory
}
anurag-jain
  • 1,380
  • 2
  • 11
  • 31
-5

Easier to try FileInfo.isDir() in qt

Varvara
  • 19