【问题标题】:How do I resolve a canonical filename in Windows?如何在 Windows 中解析规范文件名?
【发布时间】:2010-12-21 11:05:32
【问题描述】:

如果我有一个字符串可以解析为 Windows 中的文件路径,是否有一种可接受的方式来获取文件名的规范形式?

例如,我想知道是否

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

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

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

请注意,简单的字符串比较不起作用,任何 RegEx 魔法也不起作用。请记住,自 Windows 2000 和 Windows 7 中的新库结构以来,我们需要处理诸如 NTFS reparse points 之类的事情。

【问题讨论】:

  • 还有好老的subst
  • 你使用什么语言/框架?
  • 您也可以尝试在 serverfault.com 或 superuser.com 上询问此问题
  • 我正在使用 C#,但坦率地说,我很乐意使用任何可以解决此问题的语言或框架。

标签: windows filenames


【解决方案1】:

使用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:是的,我也注意到,在我阅读文档后...我改变了答案,这次实际测试了它:)
  • 这不是一个完整的解决方案,正如@Roger Lipscombe 在他的回答中指出的那样。我们可能不得不在这个问题上调用 80/20 规则。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    简短的回答:不是。

    没有简单的方法可以在 Windows 上获取文件的规范名称。本地文件可以通过重解析点,通过 SUBST 获得。您想处理 NTFS 连接吗? Windows 快捷方式? \\?\-escaped 文件名呢

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

    所以,如果您正在寻找类似 Windows 上的 inode 号之类的东西,那么它不存在。例如,请参阅this page

    【讨论】:

    • +1 链接到漂亮的博客文章“PathCanonicalize Versus What It Says On The Tin”
    • 哇。真是一团糟。为什么在 Windowsland 中没有一件容易的事?
    • -1: GetFileInformationByHandle 完全是 你所说的“类似于 inode 编号的东西”不存在。没关系。
    • 从那个页面:“根据操作系统的底层网络功能和连接的服务器类型,GetFileInformationByHandle 函数可能失败,返回部分信息,或给定文件的完整信息。"
    【解决方案4】:

    罗杰是正确的,没有简单的方法。如果卷支持文件唯一文件索引,您可以打开文件并调用GetFileInformationByHandle,但这不适用于所有卷。

    Windows API 调用GetFullPathName 可能是最好的简单方法。

    【讨论】:

    • +1... 文件索引也是唯一的 w.r.t.卷,所以你还需要卷序列号,假设它可以远程使用。
    【解决方案5】:

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

    【讨论】:

      【解决方案6】:

      GetFinalPathNameByHandle 似乎可以满足您的要求,从 Windows Vista 开始就可以使用。

      【讨论】:

        【解决方案7】:

        要获得规范路径,您应该使用PathCanonicalize 函数。

        【讨论】:

        • 不,该函数不计算规范路径,尽管它的名称。请参阅其文档的“备注”部分:该函数仅执行简单的字符串更正。例如。对于“..\someFile.txt”,当程序员期望“C:\someDir\someFile.txt”之类的东西作为规范路径时,它将返回“someFile.txt”。
        【解决方案8】:

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

        【讨论】:

          猜你喜欢
          • 2020-11-13
          • 1970-01-01
          • 1970-01-01
          • 2019-04-30
          • 2010-09-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多