Search code examples
batch-filecmdvolumewmic

Batch: list available hard drives and work with chosen option


I would like to list all available, removable hard drives in a batch script and continue to work with the chosen option. I know there are options like

wmic logicaldisk get caption,volumename

to list the hard drives and

SET /P M=Type 1 or 2 then press ENTER:
IF %M%==1 GOTO One
IF %M%==2 GOTO Two

to create a menu. But how do I store the volumes in variables and list them in a menu?

Something like:

Choose from list:

1) D:\Harddrivename1
2) E:\Harddrivename2

Enter option: 2

Any help is appreciated!


Solution

  • Here's a function that'll let you create an array of drives that are not of type 3 (fixed):

    rem // populates arrayname, arrayname.length, and arrayname.ubound
    :getRemovableDrives <arrayname>
    rem // unset array if exists
    for /f "delims==" %%I in ('2^>NUL set %~1') do set "%%~I="
    setlocal enabledelayedexpansion
    
    set /a %~1.length = 0, %~1.ubound = -1
    
    rem // note: nested for /f loops convert UCS-2 encoded WMI results to ANSI
    for /f "skip=2 delims=" %%# in (
        'wmic logicaldisk where "DriveType <> 3" get caption^,volumename /format:csv'
    ) do for /f "tokens=2,3 delims=," %%I in ("%%~#") do (
        set "%~1[!%~1.length!].caption=%%~I"
        set "%~1[!%~1.length!].volumename=%%~J"
        set /a %~1.ubound = %~1.length, %~1.length += 1
    )
    
    rem // Trick to make private variables public
    for /F "delims=" %%I in ('set %~1') do (
        if defined %~1.ubound endlocal
        set "%%~I"
    )
    exit /b
    

    Here's a full example illustrating how to use the function:

    @echo off & setlocal enabledelayedexpansion
    
    :begin
    call :getRemovableDrives drives
    
    if %drives.length% equ 0 (
        echo No removable drives found.
        exit /b 1
    )
    
    set choices=
    echo Removable drives:
    echo;
    for /L %%I in (0, 1, %drives.ubound%) do (
        set "choices=!choices!%%I"
        echo(%%I^) !drives[%%I].caption! (!drives[%%I].volumename!^)
    )
    echo(X^) exit
    set "choices=%choices%x"
    echo;
    choice /C %choices% /N /M "Press a number (or X to quit): "
    set /a choice = %ERRORLEVEL% - 1
    
    if not defined drives[%choice%].caption exit /b 0
    
    echo You chose !drives[%choice%].caption! (!drives[%choice%].volumename!^)
    goto :begin
    
    goto :EOF
    
    rem // populates arrayname, arrayname.length, and arrayname.ubound
    :getRemovableDrives <arrayname>
    rem // unset array if exists
    for /f "delims==" %%I in ('2^>NUL set %~1') do set "%%~I="
    setlocal enabledelayedexpansion
    
    set /a %~1.length = 0, %~1.ubound = -1
    
    rem // note: nested for /f loops convert UCS-2 encoded WMI results to ANSI
    for /f "skip=2 delims=" %%# in (
        'wmic logicaldisk where "DriveType <> 3" get caption^,volumename /format:csv'
    ) do for /f "tokens=2,3 delims=," %%I in ("%%~#") do (
        set "%~1[!%~1.length!].caption=%%~I"
        set "%~1[!%~1.length!].volumename=%%~J"
        set /a %~1.ubound = %~1.length, %~1.length += 1
    )
    
    rem // Trick to make private variables public
    for /F "delims=" %%I in ('set %~1') do (
        if defined %~1.ubound endlocal
        set "%%~I"
    )
    exit /b
    

    Hopefully you can use this to get you started. In case I guessed incorrectly about the drive type detection, see this page, Ctrl + F and find DriveType on the page.