Batch File: Export selection from dynamic menu to variable? - variables

OK, here goes...
I'm building a batch file with a menu that is set dynamically according to settings in multiple ini files, I used a script suggested to me in a previous question here.
Now, I need to add user input that export the selected menu option to another variable, in normal menu, that is not set dynamically it's easy enough, I've done it many times but I can't figure out how to do so in this instance.
Here's my current script:
#echo off
setlocal EnableDelayedExpansion
:LangMenu
for /L %%D in (1,1,20) do (
if exist Common\Settings\Data%%D.ini for /F "eol=# tokens=1,2 delims==" %%a in (Common\Settings\Data%%D.ini) do (
set line=%%a
if "!line:~2,5!" neq "clude" (
REM Define "normal" variables, i.e. Compressor, Method, etc.
set %%a=%%b
) else if "!line:~7!" neq "" (
REM Define the base array elements, i.e. D1IncludeAR=%%b, D1ExcludeAR=%%b, ...
set D%%D%%a=%%b
REM Set Show?? array elements with value equal 1, i.e. ShowAR=1, ...
REM when anyone of DiInclude?? or DiExclude?? corresponding elements was given
if defined D%%D%%a set Show!line:~7!=1
)
)
)
:LangContinue
REM Define a list of language abbreviations, i.e. "langs=AR CZ DE ..."
REM and the corresponding language names array, i.e. lang[AR]=Arabic, ...
REM At same time, calculate original OptNum
for %%a in ("AR=Arabic" "CZ=Czech" "DE=German" "EN=English" "ES=Spanish" "ESMX=Spanish (Mexico)"
"FR=French" "HU=Hungarian" "IT=Italian" "JP=Japanese" "KR=Korean" "PL=Polish"
"PR=Portuguese" "PRBR=Portuguese (Brazil)" "RU=Russian" "ZH=Chinese") do (
for /F "tokens=1,2 delims==" %%b in (%%a) do (
set "langs=!langs! %%b"
set "lang[%%b]=%%c"
set /A "OptNum+=Show%%b"
)
)
:LangSelect
cls
REM Show the language menu
set #=0
for %%a in (%langs%) do (
if defined Show%%a (
set /a #+=1
echo [!#!] !lang[%%a]!
)
)
set /p SelectLang=Please Choose The Language You Want:
if not "%SelectLang%"=="" Goto LangSet
if "%SelectLang%"=="" goto LangError
:LangError
cls
Echo ERROR: No Language Selected!!
pause
goto LangSelect
:LangSet
if "%SelectLang%"=="1" set LangIs=1
echo Selected Language = %LangIs%
Please note: I just put 1 in the set LangIs for the time being so I won't get echo is off message, it's not at all what I need, just a placeholder.
What I need is to set LangIs variable to the picked option...
An example:
Menu output is this:
[1] Arabic
[2] German
[3] English
[4] Spanish
[5] Italian
Please choose the language you want:
The variable language in the above example can be any languages, even up to 16 languages can be listed, the numbers are set dynamically so if available languages where different 5 languages it was still 1-5.
I need a way that the numbered choice entered by the user will write a variable with the Language name shown by it, so, for example, if the user type 5, I need a variable, that will have either "Arabic" or "AR" in it.
so, for example, if I use the echo command to show the choice it should output something like this if the number 1 is selected (in above menu example):
Selected Language = AR
or
Selected Language = Arabic
Or whatever language is assigned to the number 1 in the menu.
This variable, will have to be checked later on in my script up to 20 different times to check what language is selected in order to set another variable according to the selected language.
Any suggestions will be much appreciated.

:LangSelect
cls
REM Show the language menu
set #=0
for %%a in (%langs%) do (
if defined Show%%a (
set /A #+=1
echo [!#!] !lang[%%a]!
set "option[!#!]=%%a"
)
)
set /P "SelectLang=Please Choose The Language You Want: "
if defined option[%SelectLang%] Goto LangSet
:LangError
cls
Echo ERROR: Invalid Language Selected!!
pause
goto LangSelect
:LangSet
set "LangIs=!option[%SelectLang%]!"
echo Selected Language = %LangIs% (!lang[%LangIs%]!)

Related

Variable is empty when exporting to file

I'm trying to set a variable every time + 1 with a batch file. So when the batch file opens it calls the file with the var and then redefines it plus 1. But when i open the file and then open count.bat i see this(in count.bat): set backupcount= instead of
set backupcount=1 which it should be (1 can also be 2, 3, 4, 5, enz).
This is the code i'm using:
#echo off
if exist "backup-tool\count.bat" call "backup-tool\count.bat"
if not exist "backup-tool\count.bat" echo set backupcount=0 > "backup-tool\count.bat"
call "backup-tool\count.bat"
if "%backupcount%"=="8" (
echo set backupcount=1 > "backup-tool\count.bat"
) else (
set /a "backupcount=backupcount+=1"
echo set backupcount=%backupcount% > "backup-tool\count.bat"
)
pause >nul
Anyone that knows what i'm doing wrong and tell me how i should do it?
All help is very much appreciated!
This one needs to use setlocal ENABLEDELAYEDEXPANSION, because you work in a block of code where you manipulate that variable and you want to use it right there(not the variable that is out of the block). This should work:
#echo off
setlocal ENABLEDELAYEDEXPANSION
if exist "backup-tool\count.bat" call "backup-tool\count.bat"
if not exist "backup-tool\count.bat" echo set backupcount=0 > "backup-tool\count.bat"
call "backup-tool\count.bat"
if "!backupcount!"=="8" (
echo set backupcount=1 > "backup-tool\count.bat"
) else (
set /a "backupcount=backupcount+=1"
echo set backupcount=!backupcount! > "backup-tool\count.bat"
)
pause >nul
Your original problem is related to Delayed Expansion as other answer said; however, your code is also unnecessarily complex. This is the way I would do it:
#echo off
if exist "backup-tool\count.bat" call "backup-tool\count.bat"
set /A "backupcount=backupcount%%8+1"
echo set "backupcount=%backupcount%" > "backup-tool\count.bat"
The set /A command takes as zero the value of any non-existent variable, so it is not necessary to initialize it with zero when the data file not exists.
If you want a repeating count from 1 to 8 and then reset the counter to 1, you may use the % Modulus operator in a simpler way that don't require an if. Type set /? for further details on %% operator, or see this Wikipedia article.
EDIT: Additional explanations added
The first time the program run the backupcount variable does not exist, so the set /A "backupcount=backupcount%%8+1" expression generate a 1 that is stored in the file. You may also add a set backupcount=0 command before the if just to avoid problems with previous executions of the same Batch file (or add a setlocal command at beginning).
The next time this variable is initialized with 1, so set /A "backupcount=backupcount%%8+1" expression produce a 2. The same happen with next numbers up to 8.
When the variable is initialized with 8 the expression backupcount%%8, that is the remainder when the variable is divided by 8, is zero; so the whole expression produce a 1 again.

Batch: variable definition useable in count loop

In my batch I want to copy a variable amount of source- to target destinations.
I want to define like this:
#setlocal EnableDelayedExpansion
set source1="C:\folder1"
set target1="f:\folder1"
set source2="C:\folder2"
set target2="f:\folder2"
...
set sourcen="C:\foldern"
set targetn="f:\foldern"
Dependently from a defined amount of folders
set numFolder=5
I want to go through the folders in a loop:
set /a COUNT=0
:LOOP
echo %COUNT%
set /a COUNT+=1
rem write the NAME of the parameter variable (source1,source2 etc.) in nameor
set "nameor=source%COUNT%"
rem write the VALUE of the parameter variable (source1,source2 etc.) into origin ("C:\folder1", "C:\folder2")
set "origin=%nameor%"
echo %origin%
if %COUNT% lss %numFolder% goto LOOP
When I show
echo %nameor%
I get what I expectet: source1, source2 etc.
but
echo %%%origin%%%
only provides
source1
instead of the expected value
"C:\folder1"
I thought, that I could resolve this by using DelayedExpansion but what did I miss?
To avoid confusion for me, I change the "origin" to "source". E.g. set "origin=%nameor%" changed to set "source=%nameor%".
To print out "C:\folder1" to "C:\foldern", you should use echo !%source%!, else you will just see "source1" to "sourcen".
Your problem is just about array element management. Try this:
#echo off
setlocal EnableDelayedExpansion
rem Define the two arrays
set i=0
for %%a in ("C:\folder1=f:\folder1"
"C:\folder2=f:\folder2"
"C:\foldern=f:\foldern") do (
set /A i+=1
for /F "tokens=1,2 delims==" %%b in (%%a) do (
set source!i!="%%a"
set target!i!="%%b"
)
)
rem Show up to numFolder elements of both arrays
set numFolder=5
for /L %%i in (1,1,%numFolder%) do (
echo %%i- Source%%i=!source%%i!, Target%%i=!target%%i!
)
The first part is equivalent to your series of individual element assignments. In this way is easier to add new pairs of values.
For further description on array management in Batch files, see: Arrays, linked lists and other data structures in cmd.exe (batch) script

Batch file waits until I press enter when set b=

I've encountered a bit of an issue in a Batch script I am making.
In this script, I want to it react to my pressing a button the moment I press it, and 'set'ting a new variable without having to press Enter.
Currently, it's like this;
set b=
set /p b=
ig %b%==a (
goto Success
)
It allows me to press the button I want, however I don't want it to wait until I press Enter afterwards.
For VISTA and later
If you know your script will run on Vista or later (not XP), then you can use the choice command. You must specify which characters to accept. By default, CHOICE is case insensitive. The returned ERRORLEVEL corresponds to the position of the selected letter within the choice list.
For example, to wait for the user to press A, B, or C (case sensitive) and store the key value in a variable:
setlocal enableDelayedExpansion
set "list=ABC"
choice /cs /c "%list%"
set "list=.%list%"
set "key=!list:~%errorlevel%,1!"
echo %key%
Full documentation is available from the command line by typing HELP CHOICE or CHOICE /?
For all modern Windows, including XP
I was introduced to a very clever solution that works on XP and beyond when I was developing my batch implementation of the SNAKE game. This solution allows you to capture nearly any key press.
set "key="
for /F "usebackq delims=" %%A in (`xcopy /w "%~f0" "%~f0" 2^>NUL`) do (
if not defined key set "key=%%A"
)
set "key=%key:~-1%"
set key
use choice in batch
choice /c YN /m "Is Yes"
if ( %ERRORLEVEL% == 1 ) (
ECHO "SUCCESS"
)

How to create nested variables in batch?

I am trying to get nested variables in my batch game i am creating.
I want it so that it will choose a random variable and change it to X, but if it is already chosen, it should go back and choose a different number.
set 1=a
set 2=b
set 3=c
set 4=d
set 5=e
those were the variables, here is the code
setlocal enabledelayedexpansion
:eliminator
set /a eliminate=(%random * 5) / 32767 + 1
if %%eliminate%%==X goto eliminator
echo The letter !!eliminate!! was chosen
timeout 5
set %%eliminate%%=X
goto eliminator
Now, the thing is, when I try to echo it, it writes the name of the variable instead of the value. Also, variables that have already been chosen are being chosen again. Any way I could fix this? Thanks.
try this:
#echo off&setlocal
set "var1=a"
set "var2=b"
set "var3=c"
set "var4=d"
set "var5=e"
:loop
set /a rd=%random%%%5+1
if defined var%rd% call echo %%var%rd%%%
set "var%rd%="
set "var" >nul 2>&1 && goto:loop
..output (may vary):
d
a
c
b
e
Your posted code is missing the closing % around random - it should read %random%.
Your formula for a random number between 1 and 5 is more complicated than need be. I would use:
set /a eliminate=%random% %% 5 + 1
To expand a "nested variable" you need !%eliminate%!
But I would completely rewrite your algorithm. I think the following does what you want:
#echo off
setlocal enableDelayedExpansion
set "chars=abcde"
set charCnt=5
:loop
set /a "pos=%random% %% charCnt, pos2=pos+1, charCnt-=1"
set "letter=!chars:~%pos%,1!"
echo The letter %letter% was chosen
set "chars=!chars:~0,%pos%!!chars:~%pos2%!"
if defined chars goto loop
The script is optimized to always pick a valid unused letter on each iteration.

Variables in loops Dont Work, Batch

This is the new Script and it Still Doesn't Work
I Get The syntax of the command is incorrect.
on FOR /F "USEBACKQ tokens=*" %%A IN (TYPE "C:\Windows\System32\tasks\at!num! ^| FIND "Command") DO (
SETLOCAL ENABLEDELAYEDEXPANSION
set num=1
:START
IF NOT EXIST "C:\Windows\System32\tasks\at%num%" (GOTO:EOF)
FOR /F "USEBACKQ tokens=*" %%A IN (`TYPE "C:\Windows\System32\tasks\at!num! ^| FIND "Command"`) DO (
set var=%%A
ECHO %var%
SET /a num=%num%+1
PAUSE
)
GOTO:START
To understand your code, I'm going to break it down into logic first then try to solve it. Let me know if I miss a detail...
Set num var to 0
Begin :Loop
set num var to its current value ::NOT NEEDED - You've specified this prior to the GOTO
increment num var by +1
if myfolder\at* file exists then read at%num% and find a string then output that line to %tmp%\1.txt ::Need quotations on file location.
set F var to the line stored in %tmp%\1.txt
set F="%%F: =%%" ::Please explain what you are trying to do with this command.
set F to start on 10th character and remove the last 11 characters from the line.
echo the variable
If it doesn't exist, exit, but if it does return to :Loop
You should tell us what you are attempting. If it is as simple as saving a variable from a text file output, set F=<file.txt will work. If it didn't, then something happened prior to that command. Still... what is set F="%%F: =%%"?
Unless you are using a FOR loop variable, there is no need to use %% on each end of the variable.
If this were a FOR loop, it would look like this:
SETLOCAL ENABLEDELAYEDEXPANSION
set num=1
:START
IF NOT EXIST "myFolder\at%num%.txt" (GOTO:EOF)
FOR /F "USEBACKQ tokens=*" %%A IN (`TYPE "myFolder\at%num%.txt" ^| FIND /i "string"`) DO (
PAUSE
SET var=%%A
ECHO !var!
PAUSE
SET var=!var: =!
ECHO !var!
PAUSE
SET var=!var:~10,-11!
ECHO !var!
PAUSE
SET /a num=!num!+1
ECHO !num!
PAUSE
)
GOTO:START
One good practice to check if commands are working, such as SET, insert an ECHO on the variable and a PAUSE right after each time you believe the variable should be changed. This will track what has changed on the variable so you can see if your command was correct and the changes were made.
I'd suggest using Batch's inbuilt function for loops, see here.
Conditionally perform a command for a range of numbers
Syntax
FOR /L %%parameter IN (start,step,end) DO command
Or maybe iterating over files in a folder would be better for what you are trying to do?
Loop through files (Recurse subfolders)
Syntax
FOR /R [[drive:]path] %%parameter IN (set) DO command
Or iterating over file contents?
Loop command: against a set of files - conditionally perform
a command against each item.
Syntax
FOR /F ["options"] %%parameter IN (filenameset) DO command
FOR /F ["options"] %%parameter IN ("Text string to process") DO command
This site has plenty of examples here which should point you in the right direction.
There are a few issues with your code, I've amended as follows to get the variable populated with the contents of the temp file.
set num=0
:Loop
set /a num=%num%+1
if exist "myFolder\at*" (
TYPE "myFolder\at%num%" | FINDSTR "\<Command\>" > "%temp%\1.txt"
set /P F=<"%TEMP%\1.txt"
Echo %F%
Pause
)
I don't know if this is the problem, but have you tried enabling:
setlocal enabledelayedexpansion
Then, inside the loop (or the IF(...)), you use !foo! to signify environment variables instead of %foo%.
See setlocal /? and set /? for more information.