Archive

Archive for February, 2008

How to recursively retrieve all files in a directory tree

February 2nd, 2008 No comments

If you need to process all files or folders in an entire subtree, the following Win32/ATL code does the job. The following function recursively calls itself for all contained subfolders and adds the files found to a CAtlArray container. Obviously all this could also be done in pure C, yet since there are a few string concatenations involved, the use of ATL CString and a dynamically growing array will save a lot of additional work.

GetAllFilesRecursive is called with the path of the base folder where to start enumerating. The second argument is a pointer to a dynamically growing array. Why are we using CString instead of simple PTSTR pointers? That way we do not need to care about memory allocation and deallocation of the file names. Upon destruction of the CAtlArray class, all contained CStrings will be properly deallocated.

void GetAllFilesRecursive( PCTSTR sPath, CAtlArray<CString>* asFiles )
{
    WIN32_FIND_DATA FindFileData;
    CString s( sPath );
    s.Append( _T("\\*") );
 
    HANDLE hFind = FindFirstFile( s, &FindFileData );
    if ( hFind == INVALID_HANDLE_VALUE ) 
        return;
    else 
    {
        do 
        {
            if ( ( FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) )
            {
                if ( lstrcmp( _T("."), FindFileData.cFileName ) && lstrcmp( _T(".."), FindFileData.cFileName ) )
                {
                    s = sPath;
                    s.Append( _T("\\") );
                    s.Append( FindFileData.cFileName );
                    GetAllFilesRecursive( s, asFiles );
                }
            }
            else // file
            {
                s = sPath;
                s.Append( _T("\\") );
                s.Append( FindFileData.cFileName );
                asFiles->Add( s );
            }
        } while ( FindNextFile( hFind, &FindFileData) != 0 );
        FindClose( hFind );
    }
    return;
}

When we are dealing with directories, we have to filter out the ‘.’ and ‘..’ links which point to the current and parent directory respectively.