Best way to determine if two path reference to same file in Windows?
How would I compare 2 strings to determine if they refer to the same path in Win32 using C/C++?
While this will handle a lot of cases it misses some things:
_tcsicmp(szPath1, szPath2) == 0
For example:
forward slashes / backslashes
relative / absolute paths.
[Edit] Title changed to match an existing C# question.
Solution 1:
Open both files with CreateFile
, call GetFileInformationByHandle
for both, and compare dwVolumeSerialNumber
, nFileIndexLow
, nFileIndexHigh
. If all three are equal they both point to the same file:
GetFileInformationByHandle
function
BY_HANDLE_FILE_INFORMATION
Structure
Solution 2:
Filesystem library
Since C++17 you can use the standard filesystem library. Include it using #include <filesystem>
. You can access it even in older versions of C++, see footnote.
The function you are looking for is equivalent
, under namespace std::filesystem
:
bool std::filesystem::equivalent(const std::filesystem::path& p1, const filesystem::path& p2 );
To summarize from the documentation: this function takes two paths as parameters and returns true if they reference the same file or directory, false otherwise. There is also a noexcept
overload that takes a third parameter: an std::error_code
in which to save any possible error.
Example
#include <filesystem>
#include <iostream>
//...
int main() {
std::filesystem::path p1 = ".";
std::filesystem::path p2 = fs::current_path();
std::cout << std::filesystem::equivalent(p1, p2);
//...
}
Output:
1
Using filesystem before C++17
To use this library in versions prior to C++17 you have to enable experimental language features in your compiler and include the library in this way: #include <experimental/filesystem>
. You can then use its functions under the namespace std::experimental::filesystem
. Please note that the experimental filesystem library may differ from the C++17 one. See the documentation here.
For example:
#include <experimental/filesystem>
//...
std::experimental::filesystem::equivalent(p1, p2);
Solution 3:
See this question: Best way to determine if two path reference to same file in C#
The question is about C#, but the answer is just the Win32 API call GetFileInformationByHandle
.
Solution 4:
use the GetFullPathName from kernel32.dll, this will give you the absolute path of the file. Then compare it against the other path that you have using a simple string compare
edit: code
TCHAR buffer1[1000];
TCHAR buffer2[1000];
TCHAR buffer3[1000];
TCHAR buffer4[1000];
GetFullPathName(TEXT("C:\\Temp\\..\\autoexec.bat"),1000,buffer1,NULL);
GetFullPathName(TEXT("C:\\autoexec.bat"),1000,buffer2,NULL);
GetFullPathName(TEXT("\\autoexec.bat"),1000,buffer3,NULL);
GetFullPathName(TEXT("C:/autoexec.bat"),1000,buffer4,NULL);
_tprintf(TEXT("Path1: %s\n"), buffer1);
_tprintf(TEXT("Path2: %s\n"), buffer2);
_tprintf(TEXT("Path3: %s\n"), buffer3);
_tprintf(TEXT("Path4: %s\n"), buffer4);
the code above will print the same path for all three path representations.. you might want to do a case insensitive search after that