BAT/CMD file to remove drive letters using DISKPAR

2019-02-17 18:56发布

I am trying to write a batch file to remove drive letters that are assigned to partitions with no file system. I cannot use wmi since it is being used in a WinPE recovery environment.

DISKPART> list volume

  Volume ###   Ltr  Label          Fs              Type         Size      Status     Info
  ----------   ---  -----------   -----      ----------      -------   ---------  --------
  Volume 0       K                              DVD-ROM         0 B   No Media
  Volume 1       L                              DVD-ROM         0 B   No Media
  Volume 2       C   Windows 7    NTFS        Partition        80 GB  Healthy      System
  Volume 3       D                            Partition       500 GB  Healthy      System
  Volume 4                                    Partition       500 GB  Healthy      System
  Volume 5       E                            Partition       500 GB  Healthy      System

DISKPART> exit 

For loop = 0 to 5
If Type[loop]="Partition" then
    If Ltr[loop]<>"" then
        If Fs[loop]="" then
            SELECT VOLUME loop
            REMOVE LETTER Ltr[loop]
       End If
    End If
End If
Next

This is what I have so far...

@echo off

For /F "Tokens=1,2,3,4,5,6*" %%I In ('echo.list volume^|diskpart.exe^|findstr /I /R /C:"Volume [0-9]"') Do (
echo %%I %%J %%K %%L %%M %%N
if "%%N"=="Partition" (
if NOT "%%K"=="" (
if "%%M"=="" (
echo mountvol %%K: /D
)
)
)
)

The above does not work because the output is space delimited and some blank columns mess up the parsing.

Another attempt, I think this works, but it could be better

@echo off
cd /d "%~dp0"
for /f "skip=8 tokens=*" %%A in ('echo.list volume && echo.exit^|%windir%\system32\diskpart.exe') do (
echo.%%A ^^| find /I "       Partition" >nul && (
for /f "tokens=3 delims= " %%B in ("%%A") do (echo.mountvol %%B: /D)
)
)
pause
exit

Do you know why the above needs 2 ^ before the | (pipe) ?

@echo off
for /f "skip=9 tokens=*" %%A in ('echo.list volume^| diskpart') do (
echo."%%A"| find /I "       Partition" >nul && (
for /f "tokens=3 delims= " %%B in ("%%A") do (echo.mountvol %%B: /D & mountvol %%B: /D)
)
)
pause
exit

The above seems to be working now, I had to put double quotes around the echo."%%A" and then I removed the 2 ^ before the pipe.

@echo off
setlocal enableDelayedExpansion
set "validDrives=;C;D;E;F;G;H;I;J;K;L;M;N;O;P;Q;R;S;T;U;V;W;X;Y;Z;"
for /f "skip=9 tokens=*" %%A in ('echo.list volume^| diskpart') do (
echo."%%A"| find /I "       Partition" >nul && (
for /f "tokens=3 delims= " %%B in ("%%A") do (
if "!validDrives:;%%~B;=!" neq "!validDrives!" (echo.mountvol %%B: /D & mountvol %%B: /D)
)
)
)
pause
exit

The above is my working script, I added some code to validate the drive letter.

If anybody can offer suggestions on how to improve this then please do!

Thanks

1条回答
做自己的国王
2楼-- · 2019-02-17 19:42

I may have a much simpler solution for you. Just grab the whole line and use batch sub-strings to pull out the right pieces

@echo off
setlocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
    for /f "delims=" %%i in ('^
        echo list volume ^|^
        diskpart ^|^
        findstr Volume ^|^
        findstr /v ^
        /c:"Volume ###  Ltr  Label        Fs     Type        Size     Status     Info"^
       ') do (
        set "line=%%i"
        set letter=!line:~15,1!
        set fs=!line:~32,7!
        if not "       "=="!fs!" (
            if not " "=="!letter!" (
                call :removeVol !letter!
            )
        )
    )
endlocal
exit /b

:removeVol
    (
        echo select volume %1
        echo remove letter %1
    ) | diskpart
exit /b

The for statement produces of listing of volumes without the column headers or separators.

The do statement does the sub-string operations.

Ensure that you have admin privilege for the diskpart command. I am a bit curious about your WinRE environment. Most of the ones I've worked in did have a minimal WMI instance running, as well as WSH which would make this code much cleaner.

查看更多
登录 后发表回答