How to get size of all files in a directory

Ancient Dragon 5 Tallied Votes 4K Views Share

This shows how to get the size of all the files in a folder, and all its sub-folders on MS-Windows operating system. It uses recursion to transverse all the directories, and return a 64-bit integer. It was compiled with VC++ 2008 Express and Code::Blocks Version 8.02 with MinGW compiler.

Excizted commented: Useful code snippet. +1
#include <iostream>
#include <windows.h>
#include <string>
using namespace std;


__int64 TransverseDirectory(string path)
{
    WIN32_FIND_DATA data;
    __int64 size = 0;
    string fname = path + "\\*.*";
    HANDLE h = FindFirstFile(fname.c_str(),&data);
    if(h != INVALID_HANDLE_VALUE)
    {
        do {
            if( (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
            {
                // make sure we skip "." and "..".  Have to use strcmp here because
                // some file names can start with a dot, so just testing for the 
                // first dot is not suffient.
                if( strcmp(data.cFileName,".") != 0 &&strcmp(data.cFileName,"..") != 0)
                {
                    // We found a sub-directory, so get the files in it too
                    fname = path + "\\" + data.cFileName;
                    // recurrsion here!
                    size += TransverseDirectory(fname);
                }

            }
            else
            {
                LARGE_INTEGER sz;
                // All we want here is the file size.  Since file sizes can be larger
                // than 2 gig, the size is reported as two DWORD objects.  Below we
                // combine them to make one 64-bit integer.
                sz.LowPart = data.nFileSizeLow;
                sz.HighPart = data.nFileSizeHigh;
                size += sz.QuadPart;

            }
        }while( FindNextFile(h,&data) != 0);
        FindClose(h);

    }
    return size;
}

int main(int argc, char* argv[])
{
    __int64 size = 0;
    string path;
    size = TransverseDirectory("c:\\dvlp");
    cout << "\n\nDirectory Size = " << size << "\n";
    cin.ignore();
    return 0;
}
Excizted 67 Posting Whiz

Nice code, can be used for something, surely :)

Rajesh R Subram 127 Junior Poster in Training

Sweet, but there's an unused std::string declared in the main.

OK, I'm being a nitpick. :)

Ancient Dragon commented: I had not noticed it -- thanks. +25
marco93 -87 Junior Poster

This code is wrong.
See MSDN official sample (reparse points, etc...)

Ancient Dragon 5,243 Achieved Level 70 Team Colleague Featured Poster

>>This code is wrong.
There are as many ways to do something as there are programmers to do it. What exactly is wrong with the code I posted? Post a link to the article you site.

BTW there is no such thing as an "MSDN Official sample". They just provide samples, there is nothing "official" about them.

[edit] reparse points have nothing at all to do with the topic of this thread. So it becomes obvious you don't have the slightest clue what you are talking about.

Rajesh R Subram 127 Junior Poster in Training

MSDN isn't perfect all the time. I've corrected a bunch of erroneous "official samples", and there are some terribly gross code examples on MSDN. There are topics that are incorrectly documented about, and so on. Do you know that there's website called "connect" where you could get on and report these errors?

I do agree with Ancient Dragon - there are many ways to do the same thing, so just get over your pointless criticism.

Rajesh
Microsoft MVP, Visual C++

nezachem 616 Practically a Posting Shark

I wouldn't go that far to declare this code wrong. However, such simplistic approach is inherently dangerous. See for example this article. For more details, also look at this.

Ancient Dragon commented: good points in those links. :) +25
Ancient Dragon 5,243 Achieved Level 70 Team Colleague Featured Poster

Although that would rarly exist, here is how to avoid such directories. This also will not parse hidden directories, such as the recycle bin.

__int64 TransverseDirectory(string path)
{
    WIN32_FIND_DATA data;
    __int64 size = 0;
    string fname = path + "\\*.*";
    HANDLE h = FindFirstFile(fname.c_str(),&data);
    if(h != INVALID_HANDLE_VALUE)
    {
        cout << path << '\n';
        do {
            if( (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
            {
                if( !(data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) 
                    && !(data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
                {
                    // make sure we skip "." and "..".  Have to use strcmp here because
                    // some file names can start with a dot, so just testing for the 
                    // first dot is not suffient.
                    if( strcmp(data.cFileName,".") != 0 &&strcmp(data.cFileName,"..") != 0)
                    {
                        // We found a sub-directory, so get the files in it too
                        fname = path + "\\" + data.cFileName;
                        // recurrsion here!
                        size += TransverseDirectory(fname);
                    }
                }

            }
            else
            {
                LARGE_INTEGER sz;
                // All we want here is the file size.  Since file sizes can be larger
                // than 2 gig, the size is reported as two DWORD objects.  Below we
                // combine them to make one 64-bit integer.
                sz.LowPart = data.nFileSizeLow;
                sz.HighPart = data.nFileSizeHigh;
                size += sz.QuadPart;

            }
        }while( FindNextFile(h,&data) != 0);
        FindClose(h);

    }
    return size;
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.