Batch File - Get list value using index key - batch-file

I have written a script to bat file that will print the random value from list.
but I am facing problem to access list value using it's index
My code is:
set list=A B C D a b c
echo %list[3]%
for /l %%a in (1,1,6) do (
#set /a bottomlimit = 0
#set /a upperlimit = 5
#set /a num = !bottomlimit! + !RANDOM! %% !upperlimit! - !bottomlimit! + 1
echo %list[!num!]%
TIMEOUT /T 5
)
Waiting for your valuable solution.

Just three options. Number one to handle your approach. Number two for a "pure" array in environment variables. Number three will mix the two, definition of the list as in option 1, but iterating the list to generate the array in option 2.
#echo off
setlocal enableextensions enabledelayedexpansion
REM OPTION 1 - The list
echo -------------------------------------------------
setlocal
set "list=A B C D a b c"
set /a bottomlimit=0
set /a upperlimit=6
for /l %%a in (1,1,6) do (
set /a "num=!bottomlimit! + ( !RANDOM! %% (!upperlimit! - !bottomlimit! + 1))"
set "pos=0"
for %%l in (!list!) do if defined pos if !pos!==!num! ( echo %%l & set "pos=" ) else ( set /a "pos+=1")
)
endlocal
REM OPTION 2 - The "pure" array
echo -------------------------------------------------
setlocal
set "list[0]=A"
set "list[1]=B"
set "list[2]=C"
set "list[3]=D"
set "list[4]=a"
set "list[5]=b"
set "list[6]=c"
set /a bottomlimit=0
set /a upperlimit=6
for /l %%a in (1,1,6) do (
set /a "num=!bottomlimit! + ( !RANDOM! %% (!upperlimit! - !bottomlimit! + 1))"
for %%n in (!num!) do echo !list[%%n]!
)
endlocal
REM OPTION 3 - The remix
echo -------------------------------------------------
setlocal
set "list=A B C D a b c"
set "pos=0"
for %%l in (!list!) do ( set "list[!pos!]=%%l" & set /a "pos+=1" )
set /a "bottomlimit=0"
set /a "upperlimit=!pos!-1"
for /l %%a in (1,1,6) do (
set /a "num=!bottomlimit! + ( !RANDOM! %% (!upperlimit! - !bottomlimit! + 1))"
for %%n in (!num!) do echo !list[%%n]!
)
endlocal
endlocal
exit /b

#echo off
setlocal EnableDelayedExpansion
set list=A B C D a b c
set /a counter=1
for %%a in (%list%) do (
set "list[!counter!]=%%~a"
set /a counter=counter+1
)
set list[
for /l %%a in (1,1,6) do (
#set /a bottomlimit = 0
#set /a upperlimit = 5
#set /a num = bottomlimit + !RANDOM! %% upperlimit - bottomlimit + 1
for %%# in (!num!) do echo !list[%%#]!
TIMEOUT /T 5
)
endlocal

You may use echo/%list:~3,1%, but you can't use echo/%list:~%num%,1%
Try this:
#echo off
set "list=ABCDabc"
echo/%list:~3,1%
set /a bottomlimit = 0
set /a upperlimit = 5
for /l %%a in (1,1,6) do (
CALL:CALC
CALL _temp.bat
Timeout /t 5
)
del _temp.bat
pause >nul
exit/b
:CALC
set /a num = %bottomlimit% + %random% %% %upperlimit% - %bottomlimit% + 1
echo/set "list=%list%">_temp.bat
echo/echo/%%list:~%num%,1%%>>_temp.bat
exit/b

Related

Batch file - would like to display a menu of folders in 3 columns

1-column code is below. I'd like to expand "char" to 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz and then be able to display the options in 3 columns (21 items, 21 items, 20 items). Folder names over a certain length would have to be truncated. With 3 columns and potentially long folder names, long folder names would have to be truncated in the menu.
rem Set the number of lines per page, max 29
set "pageSize=29"
set "char=0123456789ACDEFGHIJKLMNOPQRSTUVWXYZ"
rem Load current directory contents
set "numNames=1"
for /D %%a in (*.) do (
set /A numNames+=1
set "name[!numNames!]= %%a"
)
cd ..
set /A numPages=(numNames-1)/pageSize+1
rem Show directory contents, one page at a time
set start=2
:ShowPage
set /A page=start/pageSize+1, end=start+pageSize-1
if %end% gtr %numNames% set end=%numNames%
cls
cd %folder%
echo Page %page%/%numPages% of %CD%
echo/
set "base=1"
set /A lastOpt=pageSize+base, j=base
for /L %%i in (%start%,1,%end%) do (
for %%j in (!j!) do echo !char:~%%j,1! - !name[%%i]!
set /A j+=1
)
rem Assemble the get option message
set "mssg= (B - Back): "
if %end% lss %numNames% (
if "%mssg%" equ " (B - Back): " (set "mssg= (") else set "mssg=%mssg%, "
set "mssg=!mssg!Z=Next page"
)
if "%mssg%" neq " (B - Back): " set "mssg=%mssg%): "
:GetOption
choice /C 0123456789ACDEFGHIJKLMNOPQRSTUVWXYZB /N /M "Choice%mssg%"
I've found batch file solutions to browse files/folders with GUI, but I don't want to do a call to GUI (Explorer) because I'd like to keep everything on the keyboard (slows progress down to switch back and forth between mouse and keyboard all the time).
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
rem Set the number of lines per page, max 29
set /a pageSize=29
:: my pagewidth
SET /a pagewidth=120
SET "choicenames=z0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxy"
:: remove variables starting #
FOR /F "delims==" %%e In ('set # 2^>Nul') DO SET "%%e="
FOR /L %%e IN (1,1,%pagewidth%) DO SET "#spaces=!#spaces! "
:: Read dirnames to #nn, count to #entries
FOR /d %%e IN ("%~1\*.") DO SET /a #entries+=1&SET "#!#entries!=%%e"
SET /a #entries+=1&SET "#!#entries!=z Quit."
SET /a #columns=(#entries + pagesize - 1) / pagesize
SET /a #rows=(#entries + #columns - 1)/#columns
SET /a #columnwidth=(pagewidth/#columns) - 3
SET "#choices=z"
FOR /L %%e IN (1,1,%#entries%) DO (
rem column contents - max length + terminal spaces
IF %%e neq %#entries% (
SET "#%%e=!#%%e:~-%#columnwidth%!%#spaces%"
SET "#%%e=!choicenames:~%%e,1! !#%%e:~0,%#columnwidth%!"
SET "#choices=!#choices!!choicenames:~%%e,1!"
)
)
FOR /L %%e IN (1,1,%#rows%) DO (
SET /a cols=%%e + %#rows%
SET /a #line=%%e + (%#rows% * 2^)
SET "cols=!cols! !#line!"
SET "#line=!#%%e!"
FOR %%y IN (!cols!) DO IF DEFINED #%%y SET "#line=!#line! !#%%y!"
ECHO !#line!
)
IF %#entries% gtr 36 (
choice /cs /c %#choices%
) ELSE (
choice /c %#choices%
)
IF ERRORLEVEL 2 (
ECHO ERRORLEVEL is %ERRORLEVEL%
SET /a #choices=%ERRORLEVEL%-1
CALL SET "userchoice=%%#!#choices!%%"
ECHO choice made : !userchoice:~2!
) ELSE ECHO QUIT!
GOTO :EOF
This should be a self-adjusting menu.
I chose to make the QUIT choice consistently z

Windows Batch: How do you call a variable with concentric variable names and exclamation marks?

I would like to call variables that contain other variables in their name when I have enabledelayedexpension so I would have concentric exclamation points in my variable call.
I apologize for the unclear wording; I'm not very familiar with this subject.
Here's a portion of my code that shows my issue:
set /a Freq[%%z]value[!value!]+=%%y
echo Freq %%z value !value! is !Freq[%%z]value[!value!]!
As is, batch interprets !Freq[%%z]value[!value!]! broken up into different variables with the !'s, and I don't think I can use %'s instead because I'm in a for loop where this variable is changing. I don't think I can use another for loop to replace !value! with a %%a either.
Here's a more complete look at my code:
set /a line=0
set /a goodLine=0
FOR /F "tokens=* delims=" %%x in (%file%) DO (
set /a line+=1
echo Line is !line!
set data[!line!]=%%x
set /a value=0
set /a checkGood=0
FOR %%y in (%%x) DO (
set /a value+=1
if !value!==1 (
set /a Freq=%%y
set /a checkFreq=%%y %% 10
if !checkFreq!==0 (
set /a checkGood=1
) else (echo bad)
) else (
if !checkGood!==1 (
for /l %%z in (40, 10, 330) do (
if !Freq!==%%z (
set /a Freq[%%z]value[!value!]+=%%y
echo Freq %%z value !value! is !Freq[%%z]value[!value!]!
set /a Freq[%%z]quantity[!value!]+=1
echo Freq %%z value !value! quantity is !Freq[%%z]quantity[!value!]!
)
)
) else (echo checkGood bad)
)
)
)
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET /a value=4
FOR /L %%z IN (1,1,5) DO set /a Freq[%%z]value[!value!]=%%z+10
SET Freq
ECHO ========================
FOR %%y IN (2,7) DO FOR /L %%z IN (1,1,5) DO (
set /a Freq[%%z]value[!value!]+=%%y
SET Freq[%%z]value[!value!]
CALL echo Freq %%z value !value! is %%Freq[%%z]value[!value!]%%
)
GOTO :EOF
Or you could use a for/f "tokens=2delims==" %%e in ('set Freq[%%z]value[!value!]') do echo %%e
depends on what you really want to do.

Batch Script to get value from For Loop

I've been trying to read line by line from text file. In each line, I do have "starttime" & "endtime" field in 3 & 4 th column as I highlighted below.
File1,110543,2020-07-18T03:09:12.1321687+00:00,2020-07-18T03:10:22.4097433+00:00,000001
File2,210543,2020-07-18T04:19:28.0459100+00:00,2020-07-18T04:26:08.6626472+00:00,000002
I just want to find the difference between "starttime" & "endtime" column using below script.
#Echo off&Setlocal EnableExtensions EnableDelayedExpansion
IF EXIST "%csvFilePath%tempfile.txt" (
( for /f "tokens=1-5 delims=," %%A in (%csvFilePath%tempfile.txt) do (
echo fileRecord %%A,%%B,%%C,%%D,%%E
for /f "tokens=1,2,3,4 delims=T:." %%a in ("%%C") Do (
set starttime=%%b:%%c:%%d
)
for /f "tokens=1,2,3,4 delims=T:." %%a in ("%%D") Do (
set endtime=%%b:%%c:%%d
)
echo !starttime!
echo !endtime!
set options="tokens=1-4 delims=:.,"
for /f %options% %%a in (!starttime!) do set start_h=%%a&set /a start_m=100%%b %% 100&set /a start_s=100%%c %% 100&set /a start_ms=100%%d %% 100
for /f %options% %%a in (!endtime!) do set end_h=%%a&set /a end_m=100%%b %% 100&set /a end_s=100%%c %% 100&set /a end_ms=100%%d %% 1
set /a hours=%end_h%-%start_h%
set /a mins=%end_m%-%start_m%
set /a secs=%end_s%-%start_s%
set /a ms=%end_ms%-%start_ms%
if %ms% lss 0 set /a secs = %secs% - 1 & set /a ms = 100%ms%
if %secs% lss 0 set /a mins = %mins% - 1 & set /a secs = 60%secs%
if %mins% lss 0 set /a hours = %hours% - 1 & set /a mins = 60%mins%
if %hours% lss 0 set /a hours = 24%hours%
if 1%ms% lss 100 set ms=0%ms%
:: Mission accomplished
set /a totalsecs = %hours%*3600 + %mins%*60 + %secs%
echo command took %hours%:%mins%:%secs%.%ms% (%totalsecs%.%ms%s total))))
start(03:09:12) & endtime(03:10:22) value is being printed for line1 as expected when I'm using !starttime! & !endtime!. I'm trying to pass the same variable to calculate the difference in below line.
for /f %options% %%a in (!starttime!) do set start_h=%%a&set /a start_m=100%%b %% 100&set /a start_s=100%%c %% 100&set /a start_ms=100%%d %% 100
for /f %options% %%a in (!endtime!) do set end_h=%%a&set /a end_m=100%%b %% 100&set /a end_s=100%%c %% 100&set /a end_ms=100%%d %% 1
after execution, I'm getting "0 was unexpected at this time". Can you pls help me on this
There are some issues in your code:
don't use :: as a comment. Especially within a code block. It might break your code or lead to unexpected and hard to troubleshoot results.
you need delayed expansion for all variables defined in the code block (you used delayed expansion for a few variables, but not for all.
set /a doesn't need % or ! at all (optional, but here you'd need ! instead of %).
to process a string with for /f, it needs to be quoted, or for tries to find a file with that name.
You had a superfluent pair of parentheses.
%csvFilePath% is not defined.
for /f %options% ... works, but not with delayed variables, so I moved the declaration of %options% out of the loop.
Your code was not properly indented, so the structure was hardly recognizable (I spotted the lack of delayed expansion only after indenting, which made it blatantly obvious)
Your code with all those issues fixed:
#Echo off
Setlocal EnableExtensions EnableDelayedExpansion
set "options=tokens=1-4 delims=:.,"
IF EXIST "%csvFilePath%tempfile.txt" (
for /f "tokens=1-5 delims=," %%A in (%csvFilePath%tempfile.txt) do (
echo fileRecord %%A,%%B,%%C,%%D,%%E
for /f "tokens=1,2,3,4 delims=T:." %%a in ("%%C") Do set starttime=%%b:%%c:%%d
for /f "tokens=1,2,3,4 delims=T:." %%a in ("%%D") Do set endtime=%%b:%%c:%%d
echo !starttime!
echo !endtime!
for /f "%options%" %%a in ("!starttime!") do set start_h=%%a&set /a start_m=100%%b %% 100&set /a start_s=100%%c %% 100&set /a start_ms=100%%d %% 100
for /f "%options%" %%a in ("!endtime!") do set end_h=%%a&set /a end_m=100%%b %% 100&set /a end_s=100%%c %% 100&set /a end_ms=100%%d %% 1
set /a hours=end_h-start_h
set /a mins=end_m-start_m
set /a secs=end_s-start_s
set /a ms=end_ms-start_ms
if !ms! lss 0 set /a secs = secs - 1 & set /a ms = 100!ms!
if !secs! lss 0 set /a mins = mins - 1 & set /a secs = 60!secs!
if !mins! lss 0 set /a hours = hours - 1 & set /a mins = 60!mins!
if !hours! lss 0 set /a hours = 24!hours!
if 1!ms! lss 100 set ms=0!ms!
REM Mission accomplished
set /a totalsecs = hours*3600 + mins*60 + secs
echo command took !hours!:!mins!:!secs!.!ms! (!totalsecs!.!ms!s total^)
)
)
(Note: I didn't check your math - I trust you there, as the results seem plausible)
Output with your example file:
fileRecord File1,110543,2020-07-18T03:09:12.1321687+00:00,2020-07-18T03:10:22.4097433+00:00,000001
03:09:12
03:10:22
command took 0:1:10.00 (70.00s total)
fileRecord File2,210543,2020-07-18T04:19:28.0459100+00:00,2020-07-18T04:26:08.6626472+00:00,000002
04:19:28
04:26:08
command took 0:6:40.00 (400.00s total)

Set /a not working as 2 / 2

I couldn't get %difference_two% to work It can find %difference_one% as 2 but when I make it divide 2 by 2 it doesn't display as anything.
Use the numbers 2,5,10,17,26
To get what I need.
#echo off
color 0a
title Solver
:numbers
cls
set /p first=First:
set /p second=Second:
set /p third=Third:
set /p fourth=Fourth:
set /p fifth=Fifth:
goto solve
:solve
cls
set /a second_minus_first= %second% - %first%
set /a third_minus_second= %third% - %second%
if %third_minus_second%==%second_minus_first% (
goto s
) else (
goto d
)
:d
cls
set /a fourth_minus_third= %fourth% - %third%
set /a difference= %third_minus_second% - %second_minus_first%
set /a difference_one= %fourth_minus_third% - %third_minus_second%
if %difference%==%difference_one% (
set /a difference_two= %difference_one% / 2
set /a thing= %first% - %difference_two%
cls
echo %difference_two%n Squared + %thing%
pause >nul
goto numbers
) else (
goto wrong
)
Try this:
#echo off
setlocal EnableDelayedExpansion
color 0a
title Solver
:numbers
cls
set /p first=First:
set /p second=Second:
set /p third=Third:
set /p fourth=Fourth:
set /p fifth=Fifth:
goto solve
:solve
cls
set /a second_minus_first= %second% - %first%
set /a third_minus_second= %third% - %second%
if %third_minus_second%==%second_minus_first% (
goto s
) else (
goto d
)
:d
cls
set /a fourth_minus_third= %fourth% - %third%
set /a difference= %third_minus_second% - %second_minus_first%
set /a difference_one= %fourth_minus_third% - %third_minus_second%
if %difference%==%difference_one% (
set /a difference_two= !difference_one! / 2
set /a thing= !first! - !difference_two!
cls
echo !difference_two!n Squared + !thing!
pause >nul
goto numbers
) else (
goto wrong
)
In batch, commands in a code block (between ( )) are interpreted as on the same line, so you need to use setlocal EnableDelayedExpansion and use ! instead of % inside them.

Batch FOR loop variable repeat

so my code is
FOR %%a IN (a b c) DO (FOR %%b IN (x y z) DO (echo %%a %%b &pause>nul))
but the output is
ax ay az bx by bz cx cy cz
i want one variable from each loop as ax by cz and noting else, please find it.
#echo off
setlocal EnableDelayedExpansion
rem Define first and second arrays
set i=0
for %%a in (a b c) do (
set /A i+=1
set first[!i!]=%%a
)
set i=0
for %%a in (x y z) do (
set /A i+=1
set second[!i!]=%%a
)
rem Show elements in both arrays with the same index
for /L %%i in (1,1,%i%) do echo !first[%%i]!!second[%%i]!
The same process with no arrays:
#echo off
setlocal EnableDelayedExpansion
set i=0
for %%a in (a b c) do (
set /A i+=1
set j=0
for %%b in (x y z) do (
set /A j+=1
if !i! equ !j! echo %%a%%b
)
)
You are doing it all wrong .... Try using a sequence of 1 1 3 where one is the step amount so that 1 1 3 would generate 1 2 3... The code is as follows
#echo off
For /L %%n in (1 1 3) do (
For %%c in (a b c) do (
Echo %%c%%n
)
)
Pause>null
Something like this:
#echo off
setlocal enabledelayedexpansion
set /A CNT=1
FOR %%a IN (a b c) DO (echo %%a !Cnt! &set /A Cnt+=1 &pause>nul)
#echo off
setlocal enabledelayedexpansion
set "a=cat dog horse"
set "b=bad little big"
:loop
set /a i+=1
set "x="
for /f "tokens=%i%" %%a in ("%b%") do set "x=%%a"<nul
if "%x%"=="" goto :eof
for /f "tokens=%i%" %%b in ("%a%") do ( echo %x% %%b)
goto :loop

Resources