Here's an actual working C++ implementation of iterating over every file/directory using a file wildcard characters [*?] in a file search pattern or file filter using a stack implementation and Unicode compliant to handle multiple languages.
No change required in default stack size in Visual Studio 2010 under Linker->System->Stack Reserve Size and Stack Commit Size, but if this fails to compile, then change these limits.
No change required in default stack size in Visual Studio 2010 under Linker->System->Stack Reserve Size and Stack Commit Size, but if this fails to compile, then change these limits.
#include <windows.h> #include <string> #include <vector> #include <stack> #include <iostream> #include <atlconv.h> #include <io.h> using namespace std; //--------------------------------------------------------------------------------- //Mon 27-Apr-20 1:57pm - working stack implementation of sub-dir transversal //https://metadataconsulting.blogspot.com/2020/04/C-stack-implementation-to-iterate-over-all-files-and-sub-directories-recursively-with-wildcard-search-pattern.html //--------------------------------------------------------------------------------- bool ListFiles(std::wstring path, std::wstring mask, std::vector<std::wstring>& files) { //HANDLE hFind = INVALID_HANDLE_VALUE; long h; errno_t err; _wfinddata_t ffd; std::wstring spec; std::wstring pathtemp; std::stack<std::wstring> directories; std::stack<std::wstring> transversal; if (path.length() > 0) { std::wstring::iterator it = path.end() - 1; if (*it == '\\') { path.erase(it); } } directories.push(path); transversal.push(path); files.clear(); //Enumerate all directories first, then all files //Tue 28-Apr-20 4:46pm - while (!transversal.empty()) { path = transversal.top(); spec = path + L"\\*"; transversal.pop(); h = _wfindfirst(spec.c_str(), &ffd); if (h > 0) { do { if (wcscmp(ffd.name, L".") != 0 && wcscmp(ffd.name, L"..") != 0) { pathtemp = path + L"\\" + ffd.name; if (ffd.attrib & FILE_ATTRIBUTE_DIRECTORY) { std::wcout << "searched dir: " << pathtemp + L"\\" << " \n"; directories.push(pathtemp); transversal.push(pathtemp); } } } while (_wfindnext(h, &ffd) == 0); if (GetLastError() != ERROR_NO_MORE_FILES) { _findclose(h); return false; } _findclose(h); h = -1; } } while (!directories.empty()) { path = directories.top(); spec = path + L"\\" + mask; directories.pop(); h = _wfindfirst(spec.c_str(), &ffd); //_get_errno( &err ); //shortcuts recursive sub-directories transversal, do not use /*if (err==EINVAL) { std::wcout << "ERROR: Invalid path encontered." << spec << std::endl; return false; } else if (err==ENOENT) { std::wcout << "No results for file pattern " << mask << std::endl; return false; }*/ if (h > 0) { //std::wcout << "ERROR: " << spec << " invalid path encontered.\n"; //no files found //return false; do { if (wcscmp(ffd.name, L".") != 0 && wcscmp(ffd.name, L"..") != 0) { pathtemp = path + L"\\" + ffd.name; if (!(ffd.attrib & FILE_ATTRIBUTE_DIRECTORY)) { files.push_back(pathtemp); } } } while (_wfindnext(h, &ffd) == 0); if (GetLastError() != ERROR_NO_MORE_FILES) { _findclose(h); return false; } } _findclose(h); //h = INVALID_HANDLE_VALUE; h = -1; } return true; } int main(int argc, char* argv[]) { vector<wstring> files; int cnt = 0; if (ListFiles(L"C:\\Windows\\Temp", L"*.log", files)) { for (vector<wstring>::iterator it = files.begin(); it != files.end(); ++it) { wcout << ++cnt << ". " << it->c_str() << endl; } } return 0; }
No comments:
Post a Comment