Преобразовать букву диска Windows в путь (subst и сетевой)
-
18-09-2019 - |
Вопрос
Интересно, существует ли универсальный способ разрешения пути с использованием буквы диска (например, X:\foo\bar.txt
) в эквивалентный путь UNC, который может быть одним из следующих:
X:\foo\bar.txt
еслиX:
это настоящий драйв (т.е.жесткий диск, USB-накопитель и т. д.)\\server\share\foo\bar.txt
еслиX:
это сетевой диск, установленный на\\server\share
C:\xyz\foo\bar.txt
еслиX:
является результатомSUBST
отображение командX:
кC:\xyz
Я знаю, что существуют частичные решения, которые:
Разрешить сетевой диск (см., например, вопрос 556649 который опирается на
WNetGetUniversalName
)Решить
SUBST
буква диска (см.QueryDosDevice
который работает должным образом, но не возвращает пути UNC для таких объектов, как локальные или сетевые диски).
Мне не хватает какого-то простого способа реализации разрешения буквы диска в Win32?Или мне действительно нужно связываться с обоими WNetGetUniversalName
и QueryDosDevice
чтобы получить то, что мне нужно?
Решение
Да, вам нужно будет определить букву диска самостоятельно.
WNetGetUniversalName()
подходит близко, но работает только для букв дисков, которые сопоставлены с реальными общими ресурсами UNC, что не всегда так.Не существует единой функции API, которая сделала бы всю работу за вас.
Другие советы
Вот пакет для перевода букв дисков в пути UNC или обратные подставленные пути.Хотя не гарантируется, что это сработает.
Пример использования: script.cmd echo Z: Y: W:
@echo off
:: u is a variable containing all arguments of the current command line
set u=%*
:: enabledelayedexpansion: exclamation marks behave like percentage signs and enable
:: setting variables inside a loop
setlocal enabledelayedexpansion
:: parsing result of command subst
:: format: I: => C:\foo\bar
:: variable %G will contain I: and variable H will contain C:\foo\bar
for /f "tokens=1* delims==> " %%G IN ('subst') do (
set drive=%%G
:: removing extra space
set drive=!drive:~0,2!
:: expanding H to a short path in order not to break the resulting command line
set subst=%%~sfH
:: replacing command line.
call set u=%%u:!drive!=!subst!%%
)
:: parsing result of command net use | findstr \\ ; this command is not easily tokenized because not always well-formatted
:: testing whether token 2 is a drive letter or a network path.
for /f "tokens=1,2,3 delims= " %%G IN ('net use ^| findstr \\') do (
set tok2=%%H
if "!tok2:~0,2!" == "\\" (
set drive=%%G
set subst=%%H
) else (
set drive=%%H
set subst=%%I
)
:: replacing command line.
call set u=%%u:!drive!=!subst!%%
)
call !u!