8

I'm using something like this:

std::string tempDirectory = "./test/*";

WIN32_FIND_DATA directoryHandle;
memset(&directoryHandle, 0, sizeof(WIN32_FIND_DATA));//perhaps redundant???

std::wstring wideString = std::wstring(tempDirectory.begin(), tempDirectory.end());
LPCWSTR directoryPath = wideString.c_str();

//iterate over all files
HANDLE handle = FindFirstFile(directoryPath, &directoryHandle);
while(INVALID_HANDLE_VALUE != handle)
{
    //skip non-files
    if (!(directoryHandle.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
    {
        //convert from WCHAR to std::string
        size_t size = wcslen(directoryHandle.cFileName);
        char * buffer = new char [2 * size + 2];
        wcstombs(buffer, directoryHandle.cFileName, 2 * size + 2);
        std::string file(buffer);
        delete [] buffer;

        std::cout << file;
    }

    if(FALSE == FindNextFile(handle, &directoryHandle)) break;
}

//close the handle
FindClose(handle);

which prints the names of each file in the relative directory ./test/*.

Is there any way to determine the absolute path of this directory, just like realpath() does on Linux without involving any 3rd party libraries like BOOST? I'd like to print the absolute path to each file.

Mihai Todor
  • 8,014
  • 9
  • 49
  • 86
  • Are you asking for a [UNC](http://en.wikipedia.org/wiki/Uniform_Naming_Convention#Uniform_Naming_Convention) path? – David Schwartz Sep 11 '12 at 00:22
  • I don't think I'll need such a general solution. The local path should do just fine for now (as in C:\bla\blabla\etc). – Mihai Todor Sep 11 '12 at 00:26
  • There's no guarantee there is a local path. – David Schwartz Sep 11 '12 at 00:29
  • 1
    Agreed, but in my case, the application will always run from a local drive. So, what I'm asking, in this particular case, is there an API function that can return a usable absolute path? – Mihai Todor Sep 11 '12 at 00:33
  • If you upgrade to Visual C++ 2012, you can use the `` header, which is an implementation of the proposed C++ TR2 filesystem library, based on Boost.Filesystem. [Unrelated: in your current code, you can use a `std::vector` for the `buffer` to avoid the hand-rolled `new`/`delete` pair.] – James McNellis Sep 11 '12 at 00:44
  • @JamesMcNellis I had no idea they got that header it in VS2012. I thought it was eons away from being implemented... I wonder when GCC will have it as well. – Mihai Todor Sep 11 '12 at 00:46
  • @JamesMcNellis Regarding your remark for buffer, does wcstombs play nice with std::vector? – Mihai Todor Sep 11 '12 at 00:48
  • 1
    `std::vector` is simply a dynamically-allocated array of `char`, so if you `.resize()` it to the desired size, you can call `.data()` to get a pointer to its initial element. To `wcstombs`, there is no difference between that pointer and a pointer yielded by `new`'ing an array. – James McNellis Sep 11 '12 at 00:49
  • 1
    Tip: You can eliminate the memset with `WIN32_FIND_DATA directoryHandle = { 0 };`. Valid in both C and C++. – MSalters Sep 11 '12 at 08:06

2 Answers2

10

See the GetFullPathName function.

Adi Lester
  • 24,731
  • 12
  • 95
  • 110
Jonathan Potter
  • 36,172
  • 4
  • 64
  • 79
  • 5
    Specifically, call `GetFullPathName` on the directory, and combine it with the file name in `WIN32_FIND_DATA`. – Raymond Chen Sep 11 '12 at 00:40
  • @RaymondChen, and how is that done? In my case (similar to the question) I have a path with wildcards as a string, but I only have handles for the found files. Since the path may contain wildcards, a directory may not exists, so somehow I need to get the parent directory of the found file and then get the full path for that dir? – Javier Mr Sep 20 '16 at 15:29
  • 1
    @JavierMr If you have a new question, please post a new question. I don't know what you mean by "a directory may not exist". The directory is right there: In `./test/*`, the directory is `./test`. Wildcards are not allowed in the directory portion, so getting the directory will not require you to deal with wildcards. – Raymond Chen Sep 20 '16 at 18:42
  • @RaymondChen, actually completing the code in the question to print the absolute paths would be enough. I didn't knew that wildcards where only allowed in the directory portion of the path, that definitely makes things easier – Javier Mr Sep 21 '16 at 05:44
4

You can try GetFullPathName

Or you can use SetCurrentDirectory and GetCurrentDirectory. You might want to save the current directory before doing this so you can go back to it afterwards.

In both cases, you only need to get the full path of your search directory. API calls are slow. Inside the loop you just combine strings.

paddy
  • 60,864
  • 6
  • 61
  • 103