Как мне разрешить каноническое имя файла в Windows? - PullRequest
9 голосов
/ 29 ноября 2009

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

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

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

и

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

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

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

Ответы [ 8 ]

9 голосов
/ 29 ноября 2009

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

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

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

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

4 голосов
/ 30 ноября 2009

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

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

3 голосов
/ 26 сентября 2012

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

3 голосов
/ 29 ноября 2009

Использование 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: \ вещи \ вещи \ и т.д. \ разное \ whatever.txt
C: \ вещи \ вещи \ и т.д. \ разное \ whatever.txt

1 голос
/ 29 ноября 2009
У

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 голосов
/ 10 марта 2016

Полагаю, я немного опоздал, но вы можете использовать System.IO.Path.GetFullPath ("C: \ stuff \ things \ etc \ misc \ other .. \ what.txt"), и он вернется " C: \ вещи \ вещи \ и т.д. \ разное \ whatever.txt "

0 голосов
/ 06 января 2014

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

0 голосов
/ 30 апреля 2012

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...