在Windows中如何解析规范文件名?

9
如果我有一个在Windows中解析为文件路径的字符串,是否有一种被接受的方法来获取文件名的规范形式?
例如,我想知道

C:\stuff\things\etc\misc\whatever.txt

and

C:\stuff\things\etc\misc\other\..\whatever.txt

实际上指向同一个文件或不是,并在我的应用程序中存储路径的规范形式。

请注意,简单的字符串比较不起作用,任何正则表达式也不起作用。请记住,自Windows 2000以来,我们有像NTFS重新解析点这样的东西要处理,以及Windows 7中的新库结构。


以及那个古老的subst - EFraim
你使用的是哪种编程语言/框架? - jheddings
你也可以尝试在serverfault.com或superuser.com上询问这个问题。 - DOK
我正在使用C#,但坦白地说,我很乐意使用任何能解决这个问题的语言或框架。 - dthrasher
8个回答

10

简短回答:实际上不行。

在Windows中,获取文件的规范名称并没有简单的方法。本地文件可以通过重解析点、SUBST等方式来使用。您是否想处理NTFS联接?Windows快捷方式?关于 \\?\- 转义的文件名呢?

远程文件可以通过映射的驱动器号或UNC访问。这是到原始服务器的UNC吗?您正在使用DFS吗?服务器是否使用重解析点等等?服务器是否有多个可用名称?IP地址呢?它是否有多个IP地址?

因此,如果您想要像在Linux中获取inode编号那样做,Windows中是不可能的。例如,请参阅此页面


+1 对于这篇名为“PathCanonicalize与其表面意思不符”的精彩博客文章的链接。 - sean e
4
哇,真是一团糟。为什么在Windows世界里没有什么容易的事情呢? - dthrasher
-1: GetFileInformationByHandle 正是你所说的“类似于inode号码”的东西。它确实存在。 - Roman Starkov
4
来自该页面的内容:“根据操作系统底层网络特性和连接的服务器类型,GetFileInformationByHandle函数可能会失败,返回部分信息或给定文件的完整信息。” - Roger Lipscombe
您可以检查inode:https://dev59.com/questions/Pmw05IYBdhLWcg3wkirX。 - Erik Aronesty

4
罗杰是正确的,没有简单的方法。如果卷支持文件唯一索引,则可以打开文件并调用GetFileInformationByHandle,但这在所有卷上都不起作用。Windows API调用GetFullPathName可能是最好的简单方法。

+1...同时文件索引仅相对于卷是唯一的,因此您还需要卷序列号,假设它可以远程获取。 - Roger Lipscombe

4

3

使用 FileInfo(C# 示例):

FileInfo info1 = new FileInfo(@"C:\stuff\things\etc\misc\whatever.txt");
FileInfo info2 = new FileInfo(@"C:\stuff\things\etc\misc\other\..\whatever.txt");
if (info1.FullName.Equals(info2.FullName)) {
    Console.WriteLine("yep, they're equal");
}
Console.WriteLine(info1.FullName);
Console.WriteLine(info2.FullName);

输出结果为:

是的,它们相等
C:\stuff\things\etc\misc\whatever.txt
C:\stuff\things\etc\misc\whatever.txt


我不确定Equals检查是否有用 - 据我所知,FileInfo没有覆盖Equals方法,因此这只会给您引用相等性,而不是文件路径等价性。因此,在您的示例中,info1.Equals(info2)将返回false。 - itowlson
@itowlson:是的,我也注意到了,在阅读文档后......我改变了我的回答,并实际测试了一下这次 :) - jheddings
正如 @Roger Lipscombe 在他的回答中指出的那样,这并不是一个完整的解决方案。对于这个问题,我们可能需要运用80/20法则。 - dthrasher

1
jheddings的回答很好,但由于您没有指明使用哪种语言,我想提供一种Python方法来完成它,同时也可以在命令行中使用os.path.abspath
> python -c "import os.path; print os.path.abspath('C:\stuff\things\etc\misc\other\..\whatever.txt')"
C:\stuff\things\etc\misc\whatever.txt

0

我猜我有点晚了,但是你可以使用System.IO.Path.GetFullPath("C:\stuff\things\etc\misc\other..\whatever.txt"),它会返回"C:\stuff\things\etc\misc\whatever.txt"


0
我会使用 System.IO.Path.GetFullPath。它以字符串作为输入(在您的情况下是 C:\stuff\things\etc\misc\other..\whatever.txt),并输出一个字符串(C:\stuff\things\etc\misc\whatever.txt)。

-2

不,尽管函数名字中含有"canonical path",但该函数并不计算规范路径。请参阅其文档中的“备注”部分:该函数仅进行简单的字符串更正。例如,对于".. \ someFile.txt",它将返回"someFile.txt",而程序员期望得到类似于"C:\someDir\someFile.txt"的规范路径。 - Serge Rogatch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接