Как использовать метку тома в пути Windows?
Я хочу скопировать файлы со съемного диска, используя пакетный файл, независимо от того, какую букву он получает.
Пока нет пути. Кажется, что нет никаких доступных команд или сторонних инструментов командной строки, которые бы обрабатывали пути на основе меток томов.
Я попробовал FreeFileSync, но он работает большими партиями, и мне нужны точные операции с файлами здесь. Кроме того, он не делает удаления, и мне нужно переместить файлы с Pendrive.
Однако меня интересует то, что выдача бессмысленной команды, такой как...
C:\> cd MYPENDRIVE:
... приводит к довольно интересному биту в сообщении об ошибке по умолчанию:
The filename, directory name, or volume label syntax is incorrect.
^^^^^^^^^^^^^^^^^^^
Если это сообщение заслуживает доверия, то это означает, что существует некоторый правильный синтаксис для размещения метки тома. Или нет?
Примечание: я могу согласиться на написание небольшого инструмента "getdriveletterforvolume", если придется, но я бы не стал изобретать велосипед. Кроме того, во время более длительных операций с пакетными файлами диск может быть удален и заменен другим, после чего мне потребуется прекратить операции, а не продолжать работу на другом диске, который получает такую же букву.
Примечание 2: Использование \\?\Volume{12345678.....} является последним средством, хотя его можно приручить до некоторой степени, чтобы создать элементарный пакетный файл, например...
SET PENDRIVE=\\?\Volume{949a764e-a2f0-11e3-b710-6cf04975450b}
SET BACKUPDRIVE=\\?\Volume{e79091c4-5c2a-11e3-86f9-806e6f6e6963}
if exist %PENDRIVE% {
if exist %BACKUPDRIVE% {
move %PENDRIVE%\*.* %BACKUPDRIVE%
}
}
... но это некрасиво и не позволяет мне творить чудеса, например, давать двум подвескам одинаковый ярлык, чтобы они вели себя одинаково. Я знаю, что это не частый случай, но, эй, зачем ограничивать свои варианты, когда может быть готовое решение?
Изменить: прогресс. Я изменил подпрограмму, чтобы она возвращала значение как VOLUMEID:
CALL :GetVolumeID PENDRIVE
SET "PENDRIVE=%VOLUMEID%"
IF EXIST "%PENDRIVE%\" ECHO PENDRIVE is connected at %PENDRIVE%!
GOTO :eof
:GetVolumeID
FOR /F "skip=1" %%A in ('"wmic volume where label='%~1' get deviceid 2>/null"') do (
SET "VOLUMEID=%%A"
GOTO :eof
)
GOTO :eof
... но теперь, если нет Pendrive, wmic
возвращает какое-то пустое значение (НЕ пустую строку; if %%A==""
проверить) - и так IF EXIST \
заканчивается правда. Как я могу устранить пустой результат, как это..? Я старался SET VOLUMEID=$FOO$
перед FOR
, но это переписывает это с пустым значением в любом случае.
В заключение! Вот подтверждение концепции для тех, кто считает ее полезной.
@ECHO OFF
CALL :GetVolumeID BACKUPDRIVE
SET "BACKUPDRIVE=%VOLUMEID%"
CALL :GetVolumeID PENDRIVE
SET "PENDRIVE=%VOLUMEID%"
if exist %PENDRIVE%\ (
if exist %BACKUPDRIVE%\ (
echo Emptying the pendrive.
move %PENDRIVE%\*.* %BACKUPDRIVE%\pendrive\
)
)
GOTO :eof
:GetVolumeID
SET VOLUMEID=$$$
FOR /F "tokens=1,* delims==" %%A IN ('"wmic volume where label='%~1' get deviceid /value 2>nul"') DO IF NOT "%%~B"=="" SET "VOLUMEID=%%~B"
SET "VOLUMEID=%VOLUMEID:~0,-2%"
GOTO :eof
Я добавил возвращаемое значение $ bogus, чтобы не выполнить проверку EXIST. Последняя строка SET VOLUMEID=%VOLUMEID... удаляет завершающую обратную косую черту (по некоторым причинам она считается как ДВА символа), поэтому пути записываются как %MYDRIVE%\file*.*
выглядеть вменяемым
2 ответа
Вот последнее доказательство концепции, для тех, кто считает ее полезной. Вызов GetVolumeID устанавливает переменную DRIVELETTER в качестве возврата в форме "F:".
@ECHO OFF
CALL :GetVolumeID BACKUPDRIVE
SET "BACKUPDRIVE=%DRIVELETTER%"
CALL :GetVolumeID PENDRIVE
SET "PENDRIVE=%DRIVELETTER%"
if exist %PENDRIVE%\ (
if exist %BACKUPDRIVE%\ (
echo Emptying the pendrive.
move %PENDRIVE%\*.* %BACKUPDRIVE%\pendrive\
)
)
GOTO :eof
:GetVolumeID
SET DRIVELETTER=$$$
FOR /F "tokens=1,* delims==" %%A IN ('"wmic volume where label='%~1' get deviceid /value 2>nul"') DO IF NOT "%%~B"=="" SET "DRIVELETTER=%%~B"
SET "DRIVELETTER=%DRIVELETTER:~0,-2%"
GOTO :eof
Вот подпрограмма, которая будет push
к диску по его имени. Он принимает один аргумент - метку диска:
@echo off
:pushToLabel label
setlocal
for /f "skip=1 delims=:" %%A in ('"wmic logicaldisk where VolumeName='%~1' get name"') do (
set "drive=%%A:"
goto :break
)
:break
echo %drive%
endlocal && (
pushd %drive%
)