问题
I want to copy files off a removable drive using a batch file, regardless of the drive letter it gets.
So far, no go. There don't seem to be any readily available commands or 3rd-party command-line tools that would handle paths based on volume labels.
I tried FreeFileSync, but it works in big batches, and I need precise file operations here. Also, it doesn't do deletions, and I need to MOVE files off the pendrive.
What piques my interest, however, is that issuing a nonsense command like...
C:\> cd MYPENDRIVE:
... results in quite an interesting bit in the default error message:
The filename, directory name, or volume label syntax is incorrect.
^^^^^^^^^^^^^^^^^^^
If this message is to be trusted, then it means there IS some correct syntax for putting a volume label in there. Or isn't there?
Note: I can settle for writing a small "getdriveletterforvolume" tool, if I have to, but I'd rather not reinvent the wheel. Also, during longer batch file operations the drive may be removed and replaced with another, at which point I'll need the operations to cease, and not continue on another drive that gets the same drive letter.
Note2: Using \\?\Volume{12345678.....} is a last resort, though it can be tamed to some extent, to build a rudimentary batch file like...
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%
}
}
... but it's ugly and doesn't let me do any magic like giving two pendrives the same label to have them behave identically. I know it's not a common case, but hey, why limit one's options where there might be a ready solution?
Edit: Progress. I modified the subroutine to return a value as 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
... but now if the pendrive is missing, wmic
returns some empty-like value (NOT an empty string; it fails an if %%A==""
check) - and so IF EXIST \
ends up true. How do I eliminate an empty result like that..? I tried SET VOLUMEID=$FOO$
before the FOR
, but it overwrites that with an empty value anyway.
Finally! Here's a proof of concept, for whomever finds it useful.
@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
I added the $ bogus value to be returned to fail an EXIST check.
The final SET VOLUMEID=%VOLUMEID... line removes the trailing backslash (for some reason it counts as TWO characters) so that paths written as %MYDRIVE%\file*.*
look sane.
回答1:
here's a subroutine that will push
you to a drive by its name.It takes one argument - the drive label:
@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%
)
回答2:
Here's a final proof of concept, for whomever finds it useful. Calling GetVolumeID sets a DRIVELETTER variable as return, in the "F:" form.
@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
来源:https://stackoverflow.com/questions/28325246/how-to-use-a-volume-label-in-a-windows-path