Search code examples
windowsfor-loopif-statementbatch-filegoto

How to list several items in the dialog box for execution?


How can I use a defined menu type list for running a range of selections, i.e. conditionally tick off the selected items at once.

Conventionally, the configurator looks like this:

@echo off
chcp 1251 >nul
:begin
echo  [1] Folder 1  [3] Folder 3
echo  [2] Folder 2  [4] Folder 4
set /P op=Enter the number: 
if "%op%"=="1" goto op1
if "%op%"=="2" goto op2
if "%op%"=="3" goto op3
if "%op%"=="4" goto op4
:op1
cls
call "Delete_Folder1.bat" >nul
echo Done
timeout /t 2 >nul
cls
goto begin
:op2
cls
call "Delete_Folder2.bat" >nul
echo Done
timeout /t 2 >nul
goto begin
:op3
cls
call "Delete_Folder3.bat" >nul
echo Done
timeout /t 2 >nul
cls
goto begin
:op4
cls
call "Delete_Folder4.bat" >nul
echo Done
timeout /t 2 >nul
cls
goto begin

I don't understand how to select multiple items at once. Conditionally 1 and 3, or 2, 3 and 4, That is, to list several items in a row, and have them all fulfilled.


Solution

  • The simple solution would be using a fail-safe and secure single choice solution with the Windows command CHOICE.

    @echo off
    setlocal EnableExtensions DisableDelayedExpansion
    for /F "tokens=*" %%G in ('%SystemRoot%\System32\chcp.com') do for %%H in (%%G) do set /A "CodePage=%%H" 2>nul
    %SystemRoot%\System32\chcp.com 1251 1>nul
    
    :Begin
    cls
    echo  [1] Folder 1  [3] Folder 3
    echo  [2] Folder 2  [4] Folder 4
    echo  [E] Exit
    echo(
    %SystemRoot%\System32\choice.exe /C 1234E /N /M "Enter the number or E for exit:"
    if errorlevel 5 goto EndBatch
    if not errorlevel 1 goto Begin
    echo(
    call "%~dp0Delete_Folder%ERRORLEVEL%.bat" 1>nul
    echo Done
    %SystemRoot%\System32\timeout.exe /T 2 1>nul
    goto Begin
    
    :EndBatch
    %SystemRoot%\System32\chcp.com %CodePage% 1>nul
    cls
    endlocal
    

    A more difficult solution is a multiple choice solution using set /P.

    @echo off
    setlocal EnableExtensions DisableDelayedExpansion
    for /F "tokens=*" %%G in ('%SystemRoot%\System32\chcp.com') do for %%H in (%%G) do set /A "CodePage=%%H" 2>nul
    %SystemRoot%\System32\chcp.com 1251 1>nul
    
    :Begin
    cls
    echo  [1] Folder 1  [3] Folder 3
    echo  [2] Folder 2  [4] Folder 4
    echo(
    set "UserChoice="
    set /P "UserChoice=Enter one or more space or comma separated numbers: " || goto Begin
    set "UserChoice=%UserChoice:"=%"
    if not defined UserChoice goto Begin
    echo "%UserChoice%"| %SystemRoot%\System32\findstr.exe /R /C:"^\"[1234][ ,1234]*\"$" 1>nul || goto Begin
    
    for %%I in (%UserChoice%) do if %%I GEQ 1 if %%I LEQ 4 call "%~dp0Delete_Folder%%I.bat" 1>nul
    echo Done
    
    %SystemRoot%\System32\timeout.exe /T 2 1>nul
    %SystemRoot%\System32\chcp.com %CodePage% 1>nul
    cls
    endlocal
    

    A prompt of the user for input with set /P gives a user the freedom to enter anything from an empty string to an intentionally completely wrong string or a by mistake typed wrong string.

    See: How to stop Windows command interpreter from quitting batch file execution on an incorrect user input? This answer describes very detailed both techniques used in the two batch files above.

    The following command line in second batch file needs some extra explanation:

    echo "%UserChoice%"| %SystemRoot%\System32\findstr.exe /R /C:"^\"[1234][ ,1234]*\"$" 1>nul || goto Begin
    

    It is necessary to reference the value of the environment variable UserChoice enclosed in " for getting all characters of user input string interpreted literally including characters like &<>| being otherwise interpreted as operators before the string is output with command echo which outputs also the two double quotes. See: How does the Windows Command Interpreter (CMD.EXE) parse scripts?

    The user input string enclosed in " is redirected as input to findstr which runs a case-sensitive regular expression search with interpreting the space character as literal character because of using the options /R and /C:. The regular expression search is positive only on the input string

    1. begins with " as written in the batch file,
    2. has next a digit in range 1 to 4,
    3. has optionally more spaces, commas or digits in range 1 to 4,
    4. and ends with " as written in the batch file.

    There is used 1234 and not 1-4 in the two square brackets as the latter would result in matching also ¹²³ which is not acceptable in this case.

    It is important here that no space is left to the redirection operator | because of echo would also output that space and findstr would never find a positive match with the specified expression on trailing space output by echo.

    The input validation done with findstr results in an exit with value 1 meaning no match if the user enters a string like 1, 6, 08 or 1, <batch> & test, 2 in which case the user is prompted once again.

    But an input like 1,3 4, 2 11,, ,32 4321 444444444444444444444 results in a positive find with exit code 0 and the FOR loop is run next with calling:

    "%~dp0Delete_Folder1.bat"
    "%~dp0Delete_Folder3.bat"
    "%~dp0Delete_Folder4.bat"
    "%~dp0Delete_Folder2.bat"
    

    The numbers 11, 32, 4321, 444444444444444444444 are ignored because of the two IF conditions.

    The second batch file does not prompt the user a second time because the user has the freedom to enter all four numbers at once on prompt.

    Both batch files determine the current code page before changing it to Windows-1251 and restore that code page before exiting. That is recommended for any batch file which changes the default code page in case of the user runs the batch file from within a command prompt window instead of double clicking on it in Windows File Explorer and the user continues using the command prompt with expecting usage of default code page after batch file execution finished. See Saving current codepage on DosTips for more details.

    See also:

    To understand the commands used and how they work, open a command prompt window, execute there the following commands, and read the displayed help pages for each command, entirely and carefully.

    • call /?
    • chcp /?
    • choice /?
    • cls /?
    • echo /?
    • endlocal /?
    • findstr /?
    • for /?
    • goto /?
    • if /?
    • set /?
    • setlocal /?
    • timeout /?