Size of a directory

22,893

Solution 1

As far as I am aware you have to do this with iteration on most operating systems.

You could take a look at boost.filesystem, this library has a recursive_directory_iterator, it will iterate though ever file on the system getting accumulation the size.

http://www.boost.org/doc/libs/1_49_0/libs/filesystem/v3/doc/reference.html#Class-recursive_directory_iterator

include <boost/filesystem.hpp>
int main()
{
    namespace bf=boost::filesystem;
    size_t size=0;
    for(bf::recursive_directory_iterator it("path");
        it!=bf::recursive_directory_iterator();
        ++it)
    {   
        if(!bf::is_directory(*it))
            size+=bf::file_size(*it);
    }   
}

PS: you can make this a lot cleaner by using std::accumulate and a lambda I just CBA

Solution 2

I don't think there is something like that, at least no win32 api function.

Natively for windows:

void DirectoryInfo::CalculateSize(std::string _path)
{
    WIN32_FIND_DATAA data;
    HANDLE sh = NULL;

    sh = FindFirstFileA((_path+"\\*").c_str(), &data);

    if (sh == INVALID_HANDLE_VALUE )
    {
            return;
    }

    do
    {
        // skip current and parent
        if (std::string(data.cFileName).compare(".") != 0 && std::string(data.cFileName).compare("..") != 0)
        {

            // if found object is ...
            if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)
            {
                // directory, then search it recursievly
                this->CalculateSize(_path+"\\"+data.cFileName);


            } else
            {
                // otherwise get object size and add it to directory size
                this->dirSize += (__int64) (data.nFileSizeHigh * (MAXDWORD ) + data.nFileSizeLow);
            }
        }

    } while (FindNextFileA(sh, &data)); // do

    FindClose(sh);

} 

Solution 3

You must traverse the files. Getting a correct result is tricky if there are hard-links or reparse points in the tree. See Raymond Chen's blog post for details.

Solution 4

Zilog has written quite good answer, but I would make that in similar but different way.

I have my types definition file with:

typedef std::wstring String;
typedef std::vector<String> StringVector;
typedef unsigned long long uint64_t;

and code is:

uint64_t CalculateDirSize(const String &path, StringVector *errVect = NULL, uint64_t size = 0)
{
    WIN32_FIND_DATA data;
    HANDLE sh = NULL;
    sh = FindFirstFile((path + L"\\*").c_str(), &data);

    if (sh == INVALID_HANDLE_VALUE )
    {
        //if we want, store all happened error  
        if (errVect != NULL)
            errVect ->push_back(path);
        return size;
    }

    do
    {
        // skip current and parent
        if (!IsBrowsePath(data.cFileName))
        {
            // if found object is ...
            if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)
                // directory, then search it recursievly
                size = CalculateDirSize(path + L"\\" + data.cFileName, NULL, size);
            else
                // otherwise get object size and add it to directory size
                size += (uint64_t) (data.nFileSizeHigh * (MAXDWORD ) + data.nFileSizeLow);
        }

    } while (FindNextFile(sh, &data)); // do

    FindClose(sh);

    return size;
} 

bool IsBrowsePath(const String& path)
{
    return (path == _T(".") || path == _T(".."));
}

This uses UNICODE and returns failed dirs if you want that.

To call use:

StringVector vect;
CalculateDirSize(L"C:\\boost_1_52_0", &vect);
CalculateDirSize(L"C:\\boost_1_52_0");

But never pass size

Share:
22,893
smallB
Author by

smallB

Updated on July 14, 2022

Comments

  • smallB
    smallB almost 2 years

    Is there a way to get the directory size/folder size without actually traversing this directory and adding size of each file in it? Ideally would like to use some library like boost but win api would be ok too.

  • ibell
    ibell about 9 years
    Almost works, but IsBrowsePath function is missing
  • Millie Smith
    Millie Smith about 7 years
    I'm pretty sure we need to multiply by (MAXDWORD + 1). Assuming unsigned: (uint64_t)(data.nFileSizeHigh * ((uint64_t)MAXDWORD + 1))
  • cocheci
    cocheci almost 6 years
    Using your suggestion with accumulate and lambda this becomes: auto dirSize = std::accumulate( recursive_directory_iterator("path"), recursive_directory_iterator(), 0, [](auto sz, auto entry) { return is_directory(entry) ? sz : sz + file_size(entry); });
  • thecatbehindthemask
    thecatbehindthemask over 5 years
    between the solution of 111111 and cocheci I am getting different results from the same folder :/ I am guessing which one is the wrong one.