2

I have the following code in Linux that looks for files that matches the given wildcard:

    std::vector<std::string> listFilenamesInPath(std::string wildcard = "*", std::string directory = "./")
    {
        std::vector<std::string> result;
        DIR* dirp = opendir(directory.c_str());

        if (dirp)
        {
            while (true)
            {
                struct dirent* de = readdir(dirp);

                if (de == NULL)
                    break;

                if (fnmatch(wildcard.c_str(), de->d_name, 0))
                    continue;
                else
                    result.push_back (std::string(de->d_name));
            }

            closedir(dirp);
        }

        std::sort(result.begin(), result.end());

        return result;
    }

I´m porting this code to Windows and found out that fnmatch is not available (dirent is also not available, but I could find one according to the following SO link.

Is there a fnmatch substitute function that does exactly the same thing ?

How can I make this code compile and run in a VS2012 without breaking up my logic ?

Community
  • 1
  • 1
Mendes
  • 17,489
  • 35
  • 150
  • 263
  • 1
    https://msdn.microsoft.com/en-us/library/windows/desktop/aa364418(v=vs.85).aspx The family of ``FindFirstFile(),FindNextFile()...`` functions might be what you are looking for. – BitTickler Mar 08 '16 at 20:58
  • 2
    If boost is an option it offers functions like this that work on Linux and Windows. boost::filesystem , boost::path etc. – JimmyNJ Mar 08 '16 at 20:58

2 Answers2

5

Thanks for SergeyA for the help. Here is my final solution in case someone needs in future...

#ifdef _WIN32
#include "dirent.h"
#include "windows.h"
#include "shlwapi.h"
#else
#include <dirent.h>
#include <fnmatch.h>
#endif
    std::vector<std::string> listFilenamesInPath(std::string wildcard = "*", std::string directory = "./")
    {
        std::vector<std::string> result;

        DIR* dirp = opendir(directory.c_str());

        if (dirp)
        {
            while (true)
            {
                struct dirent* de = readdir(dirp);

                if (de == NULL)
                    break;

#ifdef _WIN32
            wchar_t wname[1024];
            wchar_t wmask[1024];

            size_t outsize;
            mbstowcs_s(&outsize, wname, de->d_name, strlen(de->d_name) + 1);
            mbstowcs_s(&outsize, wmask, wildcard.c_str(), strlen(wildcard.c_str()) + 1);

            if (PathMatchSpecW(wname, wmask))
                result.push_back (std::string(de->d_name));
            else
                continue;
#else
                if (fnmatch(wildcard.c_str(), de->d_name, 0))
                    continue;
                else
                    result.push_back (std::string(de->d_name));
#endif
            }

            closedir(dirp);
        }

        std::sort(result.begin(), result.end());

        return result;
    }

Please comment if something can be improved...

Mendes
  • 17,489
  • 35
  • 150
  • 263
2

Looks like PathMatchSpec is your guy.

SergeyA
  • 61,605
  • 5
  • 78
  • 137