问题
I need to get a list of folders in the directory, but only the folders. No files are needed. Only folders. I use filters to determine if this is a folder, but they do not work and all files and folders are output.
string root = "D:\\*";
cout << "Scan " << root << endl;
std::wstring widestr = std::wstring(root.begin(), root.end());
const wchar_t* widecstr = widestr.c_str();
WIN32_FIND_DATAW wfd;
HANDLE const hFind = FindFirstFileW(widecstr, &wfd);
In this way, I check that it is a folder.
if (INVALID_HANDLE_VALUE != hFind)
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
if (!(wfd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
How to solve a problem?
回答1:
This function collects folders into given vector. If you set recursive to true, it will be scanning folders inside folders inside folders etc.
// TODO: proper error handling.
void GetFolders( std::vector<std::wstring>& result, const wchar_t* path, bool recursive )
{
HANDLE hFind;
WIN32_FIND_DATA data;
std::wstring folder( path );
folder += L"\\";
std::wstring mask( folder );
mask += L"*.*";
hFind=FindFirstFile(mask.c_str(),&data);
if(hFind!=INVALID_HANDLE_VALUE)
{
do
{
std::wstring name( folder );
name += data.cFileName;
if ( ( data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
// I see you don't want FILE_ATTRIBUTE_REPARSE_POINT
&& !( data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT ) )
{
// Skip . and .. pseudo folders.
if ( wcscmp( data.cFileName, L"." ) != 0 && wcscmp( data.cFileName, L".." ) != 0 )
{
result.push_back( name );
if ( recursive )
// TODO: It would be wise to check for cycles!
GetFolders( result, name.c_str(), recursive );
}
}
} while(FindNextFile(hFind,&data));
}
FindClose(hFind);
}
Modified from https://stackoverflow.com/a/46511952/8666197
回答2:
There are two ways to do this: The hard way, and the easy way.
The hard way is based on FindFirstFile and FindNextFile, filtering out directories as needed. You will find a bazillion samples that outline this approach, both on Stack Overflow as well as the rest of the internet.
The easy way: Use the standard directory_iterator class (or recursive_directory_iterator, if you need to recurse into subdirectories). The solution is as simple as1:
for ( const auto& entry : directory_iterator( path( L"abc" ) ) ) {
if ( is_directory( entry.path() ) ) {
// Do something with the entry
visit( entry.path() );
}
}
You will have to include the <filesystem> header file, introduced in C++17.
Note: Using the latest version of Visual Studio 2017 (15.3.5), this is not yet in namespace std. You will have to reference namespace std::experimental::filesystem instead.
1Note in particular, that there is no need to filter out the
. and .. pseudo-directories; those aren't returned by the directory iterators.
来源:https://stackoverflow.com/questions/46588859/c-folder-only-search