Possible Duplicate:
Best way to determine if two path reference to same file in C/C++
Given two file path strings with potentially different casing and slashes ('\'
vs '/'
), is there a quick way (that does not involve writing my own function) to normalize both paths to the same form, or at least to test them for equivalence?
I'm restricted to WinAPI and standard C++. All files are local.
Normalizing a path involves modifying the string that identifies a path or file so that it conforms to a valid path on the target operating system. Normalization typically involves: Canonicalizing component and directory separators. Applying the current directory to a relative path.
They indicate that the path should be passed to the system with minimal modification, which means that you cannot use forward slashes to represent path separators, or a period to represent the current directory, or double dots to represent the parent directory.
The simplest way to fix this is to: Substitute the folder that has a long file path with a drive letter (thereby shortening the overall character count for the files contained in the folder) Copy or move the files out of the folder into another folder that won't violate the limit. Delete the mapped folder.
Click the Start button and then click Computer, click to open the location of the desired file, hold down the Shift key and right-click the file. Copy As Path: Click this option to paste the full file path into a document. Properties: Click this option to immediately view the full file path (location).
May I suggest PathCanonicalize?
I found a blog posting with the most thorough, even elaborate, function I have ever seen to solve this problem. It handles anything, even horrible corner cases like V:foo.txt
where you used the subst
command to map V:
to Z:
but you already used subst
to map Z:
to some other drive; it loops until all subst
commands are unwound. URL:
http://pdh11.blogspot.com/2009/05/pathcanonicalize-versus-what-it-says-on.html
My project is pure C code, and that function is C++. I started to translate it, but then I figured out that I could get the normalized path that I wanted with one function call: GetLongPathName(). This won't handle the horrible corner cases, but it handled my immediate needs.
I discovered that GetLongPathName("foo.txt")
just returns foo.txt
, but just by prepending ./
to the filename I got the expansion to normalized form:
GetLongPathName("./foo.txt")
, if executed in directory C:\Users\steveha
, returns C:\Users\steveha\foo.txt
.
So, in pseudocode:
if the second char of the pathname is ':' or the first char is '/' or '\', just call GetLongPathName() else, copy "./" to a temp buffer, then copy the filename to temp buffer + 2, to get a copy of the filename prepended with "./" and then call GetLongPathName().
Depending on whether the paths could be relative, or contain "..", or junction points, or UNC paths this may be more difficult than you think. The best way might be to use the GetFileInformationByHandle() function as in this answer.
Edit: I agree with the comment by RBerteig that this may become hard to impossible to do if the paths are not pointing to a local file. Any comment on how to safely handle this case would be greatly appreciated.
There are odd cases. For example, "c:\windows..\data\myfile.txt" is the same as "c:\data.\myfile.txt" and "c:\data\myfile.txt". You can have any number of "\.\" and "\..\" in there. You might look into the Windows API function GetFullPathName
. It might do canonicalization for you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With