Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Normalize file path with WinAPI [duplicate]

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.

like image 381
Alex B Avatar asked Mar 26 '09 06:03

Alex B


People also ask

How do you normalize a path?

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.

What does \\ mean in Windows 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.

How do I reduce the size of a file path?

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.

How do I follow a file path?

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).


4 Answers

May I suggest PathCanonicalize?

like image 186
i_am_jorf Avatar answered Oct 15 '22 09:10

i_am_jorf


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().

like image 31
steveha Avatar answered Oct 15 '22 07:10

steveha


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.

like image 29
mghie Avatar answered Oct 15 '22 07:10

mghie


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.

like image 20
Jim Mischel Avatar answered Oct 15 '22 08:10

Jim Mischel