Skip to content

Instantly share code, notes, and snippets.

@Krzysiu
Last active September 8, 2016 00:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Krzysiu/d3dbdb3b6759baa21815a57c8e0d89cd to your computer and use it in GitHub Desktop.
Save Krzysiu/d3dbdb3b6759baa21815a57c8e0d89cd to your computer and use it in GitHub Desktop.
Windows Batch choice command: get result as character and/or use the last choice as default

The problem: Windows "choice" command, which can be used for getting one character input from user (e.g. "Are you sure [y/n]", "Choose item (1, 2, 3, 4)" etc.) returns its output as errorlevel, where value of errorlevel is equal to index of choosen character. For choices "yni", choosing "n" will return errorlevel 2, for "i" it will be "3" etc. That could make script code harder to write, read and modify. Also, for compatibility reasons, errorlevels should be checked from the biggest to the smallest. One may encounter unsuspected behavior when e.g. the result will be errorlevel 3 and conditional commands return their own errorlevel, let's say 2. In such case two conditional blocks will be executed. Complicated enough? The last straw: such behavior heavily depends on Windows version, so it may be really unexpected.

Functions: My scripts offers two functions (the latter is optional):

  1. Getting choice result not as an errorlevel variable, but as character given by user. Some tricks ensure that changing possible choices is just a matter of modyfing single variable. No adding more lines with every next choice!
  2. Saving last choice for reusing it in the next run of the script as default value. The saved choice can be also reused by external tools, scripts and in other ways.

Files: a) getChoiceCharacter.bat - get choice result as character, not number b) setLastChoiceAsDefault.bat - use choosen value as default on the next run c) setLastChoiceAsDefaultVer2.bat - same as above, but first run haven't predefined value

Licensing: (C) krzysiu.net 2016. The work is released as MIT, LGPL, GPL and CC BY 4.0 licenses. You may choose one of them. In very special cases, you may use it as public domain - I trust you can make correct... choice :) If you enjoy my script and you want to support me, you can donate me by PayPal: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=RVJ35VQGHAH6J If you liked that code, used it anywhere and you find it good, I'll be happy to hear from you.

@echo off
setlocal
rem Set here all choices
set allChoices=abc
rem Run choice with given choices
choice /c %allChoices%
rem Errorlevel is here number of character from %allChoices%
rem (1=1st choice=1st character). For getting substring of %allChoices% we
rem need to decrease it by 1 (first character have 0 index).
set /a choiceChar=%errorlevel%-1
rem Now we set %choice% to substring: index=%choiceChar%, length=1. We need to
rem use "call", as Batch substring can't take variable as an argument.
call set choice=%%allChoices:~%choiceChar%,1%%
echo Your choice is "%choice%".
endlocal
@echo off
setlocal
rem Set here all choices
set allChoices=abc
rem Set here default choice for the first run
set defChoice=b
rem Timeout for default choice.
set choiceTimeout=10
rem Temporary file with last choice. It's saved to temporary directory and
rem the name equals (scriptName)-(possibleChoices).dch, e.g. for foo.bat
rem with a, b and c choices, it'll be %temp%\foo-abc.dch. Choices are saved
rem to avoid situation when choices has changed, but file points to obsolete
rem choice. If you don't want it, change value to "%temp%\%~n0.lch"
set lastChoiceFile="%temp%\%~n0-%allChoices%.lch"
rem If default choice file exists (i.e. after fist choice), set the default
rem value to the one from file (the last choice). You may find use of last
rem choice other than choice command - use %defChoice% variable then
if exist %lastChoiceFile% set /p defChoice=<%lastChoiceFile%
rem Gives prompt (/m) with default choice in it, takes choices (/c) from
rem %allChoices% and waits 10 seconds (/t 10) to use default choice, which is
rem at first run value from 8th line or with next times the last choice.
choice /m "Choose character; default ('%defChoice%') in %choiceTimeout% seconds:" /c %allChoices% /t %choiceTimeout% /d %defChoice%
rem Get choice result as character (see getChoiceCharacter.bat)
set /a choiceChar=%errorlevel%-1
call set choice=%%allChoices:~%choiceChar%,1%%
rem Save last choice to file.
echo %choice%>%lastChoiceFile%
rem In case if you need to reset choice, use following line:
rem del %lastChoiceFile%
@echo off
setlocal
rem Set here all choices
set allChoices=abc
rem Timeout for default choice.
set choiceTimeout=10
rem Variable initialization
set "defChoice="
set "defPrompt="
set "defParams="
rem Temporary file with last choice. It's saved to temporary directory and
rem the name equals (scriptName)-(possibleChoices).dch, e.g. for foo.bat
rem with a, b and c choices, it'll be %temp%\foo-abc.dch. Choices are saved
rem to avoid situation when choices has changed, but file points to obsolete
rem choice. If you don't want it, change value to "%temp%\%~n0.lch"
set lastChoiceFile="%temp%\%~n0-%allChoices%.lch"
rem If default choice file exists (i.e. after fist choice), set the default
rem value to the one from file (the last choice). You may find use of last
rem choice other than choice command - use %defChoice% variable then. The double
rem if block is used on purpose! It avoids bug when set /p executes asynchronous
if exist %lastChoiceFile% set /p defChoice=<%lastChoiceFile%
if exist %lastChoiceFile% (
set "defParams= /t %choiceTimeout% /d %defChoice%"
set "defPrompt=; default ('%defChoice%') in %choiceTimeout% seconds"
)
rem Gives prompt (/m) with default choice in it, takes choices (/c) from
rem %allChoices% and waits 10 seconds (/t 10) to use default choice, which is
rem at first run value from 8th line or with next times the last choice.
choice /m "Choose character%defPrompt%:" /c %allChoices%%defParams%
rem Get choice result as character (see getChoiceCharacter.bat)
set /a choiceChar=%errorlevel%-1
call set choice=%%allChoices:~%choiceChar%,1%%
rem Save last choice to file.
echo %choice%>%lastChoiceFile%
rem In case if you need to reset choice, use following line:
rem del %lastChoiceFile%
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment