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.
Asked
Active
Viewed 2.7k times
21
-
7Probably not. That's why `right-click -> Properties` takes so long to run... – Mysticial Apr 04 '12 at 16:28
-
6I too don't see why this should be downvoted. This is a very valid question. Come on guys. Too localized? Really. – Niklas B. Apr 04 '12 at 16:31
-
I don't agree with the downvotes either... This is a totally valid question. – Mysticial Apr 04 '12 at 16:31
-
9*Research Effort*, which is the number one reason if you wave your mouse over that downvote button. A simple google search will provide a wealth of "You have to traverse". – Brian Roach Apr 04 '12 at 16:36
-
1IMHO, the very fact that Windows Explorer obviously performs the traversal should be hint enough. – Seva Alekseyev Apr 04 '12 at 16:39
-
Just take a look at this answer -http://stackoverflow.com/a/3308557/1155650 AND http://blogs.msdn.com/b/oldnewthing/archive/2004/12/28/336219.aspx – Rohit Vipin Mathews Jul 24 '13 at 07:38
-
@Mystical Yes, this is a valid question... that has already been asked and answered. As mentioned. Don't you feel? – luk32 Jul 24 '13 at 12:02
-
3It's funny that the question this is a "duplicate" of was asked a year after this one. Shouldn't the other question be a duplicate of this one? – callyalater May 17 '16 at 17:19
4 Answers
18
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.
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
-
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); }); – cocheci Jul 26 '18 at 14:23
-
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. – thecatbehindthemask Nov 08 '18 at 10:56
4
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);
}

Zilog
- 468
- 3
- 7
-
I'm pretty sure we need to multiply by (MAXDWORD + 1). Assuming unsigned: `(uint64_t)(data.nFileSizeHigh * ((uint64_t)MAXDWORD + 1))` – Millie Smith Mar 15 '17 at 16:28
2
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

ST3
- 8,826
- 3
- 68
- 92