问题
To get the drive the current batch resides in is easy using
set batchdrive=%~d0
But how is it possible to check if %batchdrive%
is on a local drive and not on a (mapped) network share?
Checking for %SYSTEMDRIVE%
or a fixed list "C:" "D:" ... is not reliable.
回答1:
To check whether a drive (%~d0
) is a local one, you could use a wmic
query:
wmic LogicalDisk where(DeviceID="%~d0" AND DriveType=3) get Description,DeviceID,DriveType
Given that %~d0
expands to the local drive C:
, the output looks like:
Description DeviceID DriveType Local Fixed Disk C: 3
In case %~d0
is a network drive Z:
, the error output is:
No Instance(s) Available.
Unfortunately, wmic
does not set the ErrorLevel
in case of no matches, but the above message is returned at the STDERR stream rather than the STDOUT stream, so we can apply redirection to discard STDOUT (in case the drive matches; so the get
query is omitted as it is not used anyway) and redirect STDERR to STDOUT instead (so the error message is returned at STDOUT in case):
2>&1 > nul wmic LogicalDisk where (DeviceID="%~d0" AND DriveType=3)
Hence the command line returns nothing in case %~d0
is a local drive, but something otherwise. Now let us capture the (redirected) STDOUT by a for /F
loop:
for /F "delims=" %%L in ('
2^>^&1 ^> nul wmic LogicalDisk where ^(DeviceID^="%~d0" AND DriveType^=3^)
') do echo Drive "%~d0" is not local!
So if %~d0
points to a local drive, the body of for /F
is not executed, but otherwise it is.
According to this resource, WMI and therefore the wmic
command line tool is available since Windows XP (Prof.) onward; it was not available on Windows XP Home though. wmic
does not require administrative privileges. The Win32_LogicalDisk class is available since availability of WMI. Reference the following resources for more information about WMI/wmic
: Windows Management Instrumentation: Frequently Asked Questions and WMIC - Take Command-line Control over WMI.
回答2:
The first thing to check is if batchdrive
is an unmapped network share (this happens if you start the batch file outside of cmd.exe, for example via double click or via a system call):
if "%batchdrive%" == "\\" set nshare=1
The second thing is to check if batchdrive
is in the list of network shares. These are shown with net use
, which output is similar to
status local remote network
-------------------------------------------------------------------
OK D: \\computer1\share1 Microsoft Windows Network
OK E: \\computer1\share2 Microsoft Windows Network
disconnected F: \\computer2\share Microsoft Windows Network
Command executed successfully.
Therefore we filter the output for all lines that looks like a disk drive with findstr /r /c:" [A-Z]: "
and took the second part of the output via for /f "tokens=2"
.
Complete snipped (working on WinXP and above):
if "%~d0" == "\\" (
set nshare=1
) else (
set nshare=0
for /f "tokens=2" %%a in ('net use ^| findstr /r /c:" [A-Z]: "') do (
if "%%a" == "%~d0" set nshare=1
)
)
Comments for possible issues requested :-)
来源:https://stackoverflow.com/questions/40863146/how-to-check-if-current-drive-is-on-a-local-disk-cmd