【发布时间】:2010-10-15 15:24:56
【问题描述】:
可能重复:
Best way to determine if two path reference to same file in C/C++
给定两个可能不同大小写和斜杠的文件路径字符串('\' 与 '/'),是否有一种快速方法(不涉及编写我自己的函数)将两个路径标准化为相同的形式,或者在至少要测试它们的等效性?
我仅限于 WinAPI 和标准 C++。所有文件都是本地文件。
【问题讨论】:
可能重复:
Best way to determine if two path reference to same file in C/C++
给定两个可能不同大小写和斜杠的文件路径字符串('\' 与 '/'),是否有一种快速方法(不涉及编写我自己的函数)将两个路径标准化为相同的形式,或者在至少要测试它们的等效性?
我仅限于 WinAPI 和标准 C++。所有文件都是本地文件。
【问题讨论】:
我可以推荐PathCanonicalize吗?
【讨论】:
PathCanonicalize("../foo.txt") 总是返回 /foo.txt! PathCanonicalize() 只是对字符串进行微不足道的编辑,上面的损坏是记录在案的行为。无用。我将用我发现的内容发布另一个答案。
我找到了一篇博客文章,其中包含我所见过的解决此问题的最彻底、甚至最详尽的功能。它可以处理任何事情,甚至是像V:foo.txt 这样可怕的极端情况,您使用subst 命令将V: 映射到Z:,但您已经使用subst 将Z: 映射到其他驱动器;它循环直到所有subst 命令都被解除。网址:
http://pdh11.blogspot.com/2009/05/pathcanonicalize-versus-what-it-says-on.html
我的项目是纯 C 代码,而那个函数是 C++。我开始翻译它,但后来我发现我可以通过一个函数调用获得我想要的规范化路径:GetLongPathName()。这不会处理可怕的极端情况,但它可以满足我的迫切需求。
我发现GetLongPathName("foo.txt") 只是返回foo.txt,但只是通过在文件名前面加上./ 我得到了规范化形式的扩展:
GetLongPathName("./foo.txt"),如果在目录C:\Users\steveha中执行,则返回C:\Users\steveha\foo.txt。
所以,在伪代码中:
如果路径名的第二个字符是 ':' 或第一个字符是 '/' 或 '\',只需调用 GetLongPathName() 否则,将“./”复制到临时缓冲区,然后将文件名复制到临时缓冲区 + 2,以获取前缀为“./”的文件名的副本,然后调用 GetLongPathName()。
【讨论】:
subst 命令,到目前为止,我的简单 C 代码运行良好。
subst 仍然存在......它甚至存在于 Win7 64 位,但如果不是更早的话,它可以追溯到 DOS 5.0。 Win7 带有一堆用于向后兼容的 JUNCTIONS。这让我的一些旧的 Perl 脚本在文件系统中游荡,因为它们不是目录,当然也不是文件。一个例子是C:\Documents and Settings 是一个映射到C:\Users 的JUNCTION。
GetFullPathName()? msdn.microsoft.com/en-us/library/windows/desktop/…
GetLongPathName() 而不是GetFullPathName()。我链接的那篇 2009 年的博客帖子显示了使用 GetFullPathName() 的代码,如果它对那个人来说足够好,我相信这是一个好方法。
根据路径是否是相对的、是否包含“..”、连接点或 UNC 路径,这可能比您想象的要困难。最好的方法可能是使用 GetFileInformationByHandle() 函数,如this answer。
编辑:我同意 RBerteig 的评论,即如果路径不指向本地文件,这可能会变得难以实现。任何关于如何安全处理此案例的评论将不胜感激。
【讨论】:
有一些奇怪的情况。例如,“c:\windows..\data\myfile.txt”与“c:\data.\myfile.txt”和“c:\data\myfile.txt”相同。您可以在其中包含任意数量的“\.\”和“\..\”。您可能会查看 Windows API 函数 GetFullPathName。它可能会为您进行规范化。
【讨论】: