Introduction
I've come across countless situations where routinely used utilitarian functions are simply not available, and coders simply have
to write and rewrite them many times over. This is my first article in a series of articles which will try to provide a collection of routinely
used functions with example applications on how to use them, in the hope that they will be as useful to the many developers out there as it has been to me.
One such function is to obtain a list of all files (their absolute paths) given a directory to start with, with options to search
recursively into sub-directories or just to output the files present directly under the given directory.
I've found this to be extremely useful in many projects which required going through each file for some reason or the other.
Background
This function was developed many years ago when I stumbled upon a barrage of projects that required reading into every file in a given
directory, and also provide progress information in real time, e.g., which file is being currently processed, total number of files, and
number of files already processed. Since then, I've probably used this function in a few dozen projects.
Using the Code
Follow these simple steps to use the code in your project:
- Add the files Util.h and Util.cpp into your Visual Studio C++ project (or any other kind of project, I have never used the
code on anything other than Visual Studio C++ projects, so any input on using it on other C++ projects is appreciated).
- Add the line
#include "Util.h"
in the top section of the *.cpp files you intend to use this function in. - Declare a vector of
_tstring
's: vector <_tstring> vecstrFileList;
. - Call the static function "
GetFileList()
" with the required parameters. - The vector will now have all the file paths found in the directory specified, each element of the vector being a string representing the
absolute path of a file. Note that you must explicitly clear the vector before reusing it, unless you want the function to append to the vector.
The function will also work on network drive directory paths.
- Take a look at the "Get file list" button event handler function in the source code to see steps 1 to 5 in action.
- Check the "Util.cpp" source file, or the code snippet below, for a detailed description of how the function is working
internally, it is extensively commented.
void CUtil::GetFileList(const _tstring& strTargetDirectoryPath,
const _tstring& strWildCard, bool bLookInSubdirectories,
vector<_tstring>& vecstrFileList)
{
if(strTargetDirectoryPath.compare(_T("")) == 0)
{
return;
}
_tstring strCurrentDirectory = RemoveDirectoryEnding(strTargetDirectoryPath);
WIN32_FIND_DATA fdDesktop = {0};
_tstring strDesktopPath = _T("");
strDesktopPath += _T("\\\\?\\");
strDesktopPath += strCurrentDirectory;
strDesktopPath = AddDirectoryEnding(strDesktopPath);
if(strWildCard.compare(_T("")) == 0)
{
strDesktopPath += _T("*.*");
}
else
{
strDesktopPath += strWildCard;
}
HANDLE hDesktop = ::FindFirstFile(strDesktopPath.c_str(), &fdDesktop);
if(hDesktop == INVALID_HANDLE_VALUE)
{
return;
}
do
{
_tstring strPath = _T("");
strPath += strCurrentDirectory;
strPath = AddDirectoryEnding(strPath);
strPath += fdDesktop.cFileName;
if(fdDesktop.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
_tstring strCurrentDirectoryName = GetDirectoryName(strPath);
if((strCurrentDirectoryName.compare(_T(".")) == 0) ||
(strCurrentDirectoryName.compare(_T("..")) == 0))
{
continue;
}
else
{
if(bLookInSubdirectories)
{
GetFileList(strPath, strWildCard, bLookInSubdirectories,
vecstrFileList);
}
}
}
else
{
vecstrFileList.push_back(_tstring(strPath));
}
}
while(::FindNextFile(hDesktop, &fdDesktop) == TRUE);
::FindClose(hDesktop);
}
Points of Interest
The code provided here is for unmanaged C++; if you are using managed code or C#, which uses the .NET Framework, you can use the Directory.GetFiles
methods;
you can read about it here.
While writing this code, I found that, to my annoyance, Microsoft Windows does not have any easy to use unmanaged C++ code to actually do
this in a straightforward and simple manner. If you do find this code useful, please leave a comment, it could make my day
Known Issues
When recursively finding files in sub-directories using a wild card, if the parent directory does not have at least one such file, the nested directories will not be searched.
History
- V1.0 - Initial release.
- V1.1 - Fixed recursive sub-directory search.