How can I find the size of all files located inside a folder?

20,960

Solution 1

Actually I don't want to use any third party library. Just want to implement in pure c++.

If you use MSVC++ you have <filesystem> "as standard C++". But using boost or MSVC - both are "pure C++".

If you don’t want to use boost, and only the C++ std:: library this answer is somewhat close. As you can see here, there is a Filesystem Library Proposal (Revision 4). Here you can read:

The Boost version of the library has been in widespread use for ten years. The Dinkumware version of the library, based on N1975 (equivalent to version 2 of the Boost library), ships with Microsoft Visual C++ 2012.

To illustrate the use, I adapted the answer of @Nayana Adassuriya , with very minor modifications (OK, he forgot to initialize one variable, and I use unsigned long long, and most important was to use: path filePath(complete (dirIte->path(), folderPath)); to restore the complete path before the call to other functions). I have tested and it work well in windows 7.

#include <iostream>
#include <string>
#include <filesystem>
using namespace std;
using namespace std::tr2::sys;

void  getFoldersize(string rootFolder,unsigned long long & f_size)
{
   path folderPath(rootFolder);                      
   if (exists(folderPath))
   {
        directory_iterator end_itr;
        for (directory_iterator dirIte(rootFolder); dirIte != end_itr; ++dirIte )
        {
            path filePath(complete (dirIte->path(), folderPath));
           try{
                  if (!is_directory(dirIte->status()) )
                  {
                      f_size = f_size + file_size(filePath);                      
                  }else
                  {
                      getFoldersize(filePath,f_size);
                  }
              }catch(exception& e){  cout << e.what() << endl; }
         }
      }
    }

int main()
{
    unsigned long long  f_size=0;
    getFoldersize("C:\\Silvio",f_size);
    cout << f_size << endl;
    system("pause");
    return 0;
}

Solution 2

How about letting OS do it for you:

long long int getFolderSize(string path) 
{
    // command to be executed
    std::string cmd("du -sb ");
    cmd.append(path);
    cmd.append(" | cut -f1 2>&1");

    // execute above command and get the output
    FILE *stream = popen(cmd.c_str(), "r");
    if (stream) {
        const int max_size = 256;
        char readbuf[max_size];
        if (fgets(readbuf, max_size, stream) != NULL) {
            return atoll(readbuf);
        }   
        pclose(stream);            
    }           
    // return error val
    return -1;
}

Solution 3

You may use boost in this way. You can try to optimize it some deeper.

#include <iostream>
#include <string>
#include <boost/filesystem.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/algorithm/string.hpp>



    using namespace std;
    namespace bsfs = boost::filesystem; 

    void  getFoldersize(string rootFolder,long & file_size){
        boost::replace_all(rootFolder, "\\\\", "\\");   
        bsfs::path folderPath(rootFolder);                      
        if (bsfs::exists(folderPath)){
            bsfs::directory_iterator end_itr;

            for (bsfs::directory_iterator dirIte(rootFolder); dirIte != end_itr; ++dirIte )
            {
                bsfs::path filePath(dirIte->path());
                try{
                    if (!bsfs::is_directory(dirIte->status()) )
                    {

                        file_size = file_size + bsfs::file_size(filePath);                      
                    }else{
                        getFoldersize(filePath.string(),file_size);
                    }
                }catch(exception& e){               
                    cout << e.what() << endl;
                }
            }
        }

    }

    int main(){
        long file_size =0;
        getFoldersize("C:\\logs",file_size);
        cout << file_size << endl;
        system("pause");
        return 0;
    }

Solution 4

Size of files in a folder Please have a look at this link

#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;
}

For more detail PLease CLick Here

Solution 5

Something like this would be better to avoid adding symbolic(soft) links:

std::uintmax_t directorySize(const std::filesystem::path& directory)
{
    std::uintmax_t size{ 0 };
    for (const auto& entry : std::filesystem::recursive_directory_iterator(directory))
    {
        if (entry.is_regular_file() && !entry.is_symlink())
        {
            size += entry.file_size();
        }
    }
    return size;
}
Share:
20,960
CodeRider
Author by

CodeRider

Software Engineer,India. Developing applications using VC++,C++,MFC,Opengl

Updated on September 18, 2021

Comments

  • CodeRider
    CodeRider over 2 years

    Is there any API in for getting the size of a specified folder?

    If not, how can I get the total size of a folder including all subfolders and files?

    • Kiril Kirov
      Kiril Kirov about 11 years
      Size of folder? Or size of all files, located in the folder? And which OS?
    • CodeRider
      CodeRider about 11 years
      ya I meant size of all files in the folder.And the OS is windows
    • Daniel Frey
      Daniel Frey about 11 years
      You'll need a library, for example Boost.Filesystem.
    • Cyrille
      Cyrille about 11 years
      Almost same question here
    • CodeRider
      CodeRider about 11 years
      @Daniel Frey. Actually I don't want to use any third party library. Just want to implement in pure c++.Any way thanks for the info.
    • CodeRider
      CodeRider about 11 years
      @Cyrille I saw that one, but just want to know if a single api can do that for me.
    • qPCR4vir
      qPCR4vir about 11 years
      Are you using MSVC++ ??
  • Kiril Kirov
    Kiril Kirov about 11 years
    This is not a good answer. "Extract" some of the important points from this link and write them here. You may leave the link for "more details".
  • Akanksh
    Akanksh about 11 years
    @meh good point, the link might go stale and would then be of no use to subsequent users asking the same question.
  • CodeRider
    CodeRider about 11 years
    Thank u all for the kind support.
  • CodeRider
    CodeRider about 11 years
    Sorry that I cant give you an upvote since I dont have enough reputation. Anyway its a different approach
  • Steve Valliere
    Steve Valliere about 11 years
    I don't think GetFileSize() works on folders/directories and the question is about getting the total size of a directory's content. At least, as I understand the question.
  • qPCR4vir
    qPCR4vir about 11 years
    +1: but you forgat to initialize file_size, and probably you need to path filePath(complete (dirIte->path(), folderPath));
  • qPCR4vir
    qPCR4vir about 11 years
    hmmm... there are many "wraper": MFC, .NET, Qt, etc. Are all bad?
  • JP Cordova
    JP Cordova about 11 years
    Not bat or wrong, from my point of view and as I understand, C++ libraries aim to improve portability and hide complications of direct use of underlayer functions and methods offer for the operative systems (big picture). In this case the effort to read directories and summarize file sizes are not different from OS methods and C++ libraries like boost, as you can see in all examples shared in this posts.
  • qPCR4vir
    qPCR4vir about 11 years
    Well, I can: +1. Honestly, I don't understand how this work...(a link??). Also better return long long.
  • qPCR4vir
    qPCR4vir about 11 years
    Of course, I partialy agree with you. But partcularly learning Win32 is sometimes ...hard, and not very C++ (the Q was: a C++ API). Thank for the answer.
  • Amit
    Amit about 11 years
    I am just using popen (mkssoftware.com/docs/man3/popen.3.asp) to run 'du' (disk usage) command and parsing the output returned by that. I mostly use this approach to debug code where I suspect it could be dying due to some system related issue (say doing 'stat' on file I was reading). I modified it to return long long int as you suggested.
  • Damon
    Damon almost 11 years
    @krimir: Not unless you install UnxUtils or MSYS or a similar package that contains du and cut as well as bash first, and not unless you modify it, because as it is (using pipe and output redirection), it sure won't work.
  • hennessy
    hennessy over 10 years
    What has to be included to get this code to work? I feel like Ive tried everthing and I still keep getting errors. Ive included windows.h and tried a bunch of other things along with it, it still doesnt work.
  • ST3
    ST3 over 10 years
    @hennessy you need to include vector, string, Windows.h. It looks like thats all, what error do you get?
  • hennessy
    hennessy over 10 years
    Now I tried with these included: #include <windows.h> #include <string> #include <vector> - Error: cannot convert 'const wchar_t*' to 'LPCSTR {aka const char*}' for argument '1' to 'void* FindFirstFileA(LPCSTR, LPWIN32_FIND_DATAA)'| - and - error: 'IsBrowsePath' was not declared in this scope| - and - error: no match for 'operator+' (operand types are 'std::basic_string<wchar_t>' and 'CHAR [260] {aka char [260]}')| ----- I have the 3 typedefs that you made above the function in main.cpp, so its like first the includes, then typedefs, then the CalculateDirSize function and then main().
  • hennessy
    hennessy over 10 years
    I am compiling with Code::Blocks using MinGW if that matters in this case.
  • ST3
    ST3 over 10 years
    Your project doesn't use UNICODE, you need either use UNICODE or use std::string instead of std::wstring
  • hennessy
    hennessy over 10 years
    Thanks that one helped, I changed std:wstring to std::string and removed the L that was infront of the "//" at the 2 places. What about the IsBrowsePath, though, I have tried declaring it but I just cant figure out how to use it. I still keep getting this error: . \main.cpp|54|error: 'IsBrowsePath' was not declared in this scope| -- It seems to be the last problem that I cant figure out.
  • ybdesire
    ybdesire about 4 years
    what is complete() from ?
  • chinnychinchin
    chinnychinchin almost 4 years
    First: dirIte->path() is sufficient for populating the filePath properly. "complete()" is not necessarily. Second: getFoldersize recursive call in the else body, should take filePath as a string ( can use filePath.string() if you are using experimental/filesystem v1 with C++17/20)