Как разрешить каноническое имя файла в Windows?

Если у меня есть строка, которая разрешает путь к файлу в Windows, есть ли принятый способ получить каноническую форму имени файла?

например, я хотел бы знать, является ли

C:stuffthingsetcmiscwhatever.txt

и

C:stuffthingsetcmiscother..whatever.txt

фактически указывают на тот же файл или нет, и хранят каноническую форму пути в моем приложении.

обратите внимание, что простые сравнения строк не будут работать, как и магия регулярных выражений. Помните, что у нас есть такие вещи, как файловой системы NTFS точки повторного разбора для работы с Windows 2000 и новой структурой библиотек в Windows 7.

8 ответов


короткий ответ: не совсем.

нет простого способа получить каноническое имя файла в Windows. Локальные файлы могут быть доступны через точки повторной обработки, через SUBST. Вы хотите иметь дело с соединениями NTFS? Ярлыков Windows? Насчет \?\-сбежал имена

удаленные файлы могут быть доступны через сопоставленную букву диска или через UNC. Это UNC для исходного сервера? Вы используете DFS? Сервер использует точки повторного разбора и т. д.? Доступен ли сервер более чем одно имя? Как насчет IP-адреса? Имеет ли он более одного IP-адреса?

Итак, если вы ищете что-то вроде номера inode на Windows, его там нет. См., например, на этой странице.


Роджер прав, нет простого способа. Если том поддерживает файл с уникальным индексом файла, вы можете открыть файл и вызвать GetFileInformationByHandle, но это не будет работать на всех томах.

вызов API Windows GetFullPathName может быть лучшим простым подходом.


используя 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


GetFinalPathNameByHandle появляется, чтобы сделать то, что вы просите, что доступно, начиная с Windows Vista.


jheddings имеет хороший ответ, но поскольку вы не указали, какой язык вы используете, я подумал, что дам способ Python сделать это, который также работает из командной строки, используя os.путь.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

Я бы использовал систему.ИО.Путь.GetFullPath. Он принимает строку в качестве входных данных (C:\stuff\things\etc\misc\other - ... .\все.txt в вашем случае) и выведет строку (C:\stuff\things\etc\misc\whatever - ... формат txt.)


Я думаю, я немного опоздал, но вы можете использовать систему.ИО.Путь.GetFullPath("C:\stuff\things\etc\misc\other..\whatever.txt") и он вернется "C:\stuff\things\etc\misc\whatever - ... txt"


чтобы получить канонический путь, вы должны использовать PathCanonicalize