In this piece of code I'm trying to make a list fit the screen in WinPE by alternating into two columns. But when I put !modelsvar[%increment%]:~20! in the echo it returns only ~20. Strange because !modelsvar[%%D]:~20! works fine. I've tried many variations of ! and % but no luck. Anyone know if there's is a specific rule that I'm missing?
I have setlocal enabledelayedexpansion enabled
set modelsx=%counter%
set /a counter=0
for /l %%D in (1,2,%modelsx%) do (
set /a counter+=1
set /a increment=!counter!+1
ECHO !counter!. !modelsvar[%%D]:~20! !increment!. !modelsvar[%increment%]:~20!
set /a counter+=1
)
for /l %%D in (1,2,%modelsx%) do (
set /a counter+=1
set /a increment=counter+1
for %%X in (!increment!) do (
ECHO !counter!. !modelsvar[%%D]:~20! !increment!. !modelsvar[%%X]:~20!
)
set /a counter+=1
)
Further details at Arrays, linked lists and other data structures in cmd.exe (batch) script
You're expanding increment immediately within ECHO, that is like %increment%, so the returned value is the one before the for loop executes.
Here is another work-around:
set modelsx=%counter%
set /a counter=0
for /l %%D in (1,2,%modelsx%) do (
set /a counter+=1
set /a increment=!counter!+1
call ECHO !counter!. !modelsvar[%%D]:~20! !increment!. %%modelsvar[!increment!]:~20%%
set /a counter+=1
)
Related
Inside the for loop I'm trying to access the element at index count in CLs (this line of code: echo !!CLs[!count!]!!) , but I'm not sure how to do this. I don't really understand how expansion works in this case, so what you see below it me trying something out of no where.
#ECHO off
setlocal enableextensions enabledelayedexpansion
SET CLs[0]=#
SET /A count = 0
FOR /F "tokens=5" %%I IN ('some command') DO (
echo !!CLs[!count!]!! :: THIS LINE
IF NOT %%I == CLs[!count!] (
SET /A count += 1
SET CLs[!count!]=%%I
)
)
echo The item is %CLs[10]%
endlocal
Thanks
According to the post How does the Windows Command Interpreter (CMD.EXE) parse scripts? (see phase 5), the line echo !!CLs[!count!]!! cannot work, because the opening !! are collapsed to a single !, then !CLs[! is expanded to an empty string (assuming such variable is not defined), then count is returned literally, then !]! is expanded to an empty string and the final ! is dismissed. Or in other words, delayed expansion cannot be nested.
You can use call though to introduce another parsing phase, like this:
call echo %%CLs[!count!]%%
The line IF NOT %%I == CLs[!count!] ( ... ) is wrong, you must expand the right value too. However, call if will not help unfortunately, because if (like for and rem) is a special command that is recognised by the parser earlier than others, like call.
To work around that you can store the value of !count! in a for meta-variable, like %%J, for instance, to introduce another parsing phase, and use !CLs[%%J]! then, like this:
set /A "count=0"
for /F "tokens=5" %%I in ('some command') do (
for %%J in (!count!) do (
echo !CLs[%%J]!
if not "%%I" == "!CLs[%%J]!" (
set /A "count+=1"
set "CLs[!count!]=%%I"
)
)
)
Another yet slower possibility is to put the relevant code into a sub-routine:
set /A "count=0"
for /F "tokens=5" %%I in ('some command') do (
call :SUB !count!
)
goto :EOF
:SUB
echo !CLs[%~1]!
if not "%%I" == "!CLs[%~1]!" (
set /A "count+=1"
set "CLs[%~1]=%%I"
)
goto :EOF
You may also take a look at the post Arrays, linked lists and other data structures in cmd.exe (batch) script about how to deal with such pseudo-arrays.
ECHO ------------- START AT %time%
REM <!-- language: lang-dos -->
#ECHO Off
setlocal enableextensions ENABLEDELAYEDEXPANSION
SET "sourcedir=U:\sourcedir"
SET "filename1=%sourcedir%\q58209698.txt"
SET CLs[0]=#
SET /a clscnt[0]=0
SET /A count = 0
FOR /F "tokens=*" %%I IN ('type %filename1%') DO (
SET "processed="
FOR /f "tokens=1,2,3delims=[]=" %%a IN ('set cls[') DO IF /i "%%a"=="cls" (
IF "%%I"=="%%c" (SET /a clscnt[%%b]+=1&SET "processed=y")
)
IF not DEFINED processed SET /a count+=1&SET "cls[!count!]=%%I"&SET /a clscnt[!count!]=1
)
FOR /L %%a IN (0,1,%count%) DO ECHO !clscnt[%%a]! times !cls[%%a]!
ENDLOCAL
ECHO -------------------------Second way -----------------
#ECHO Off
setlocal enableextensions ENABLEDELAYEDEXPANSION
SET "sourcedir=U:\sourcedir"
SET "filename1=%sourcedir%\q58209698.txt"
SET CLs[0]=#
SET /a clscnt[0]=0
SET /A count = 0
FOR /F "tokens=*" %%I IN ('type %filename1%') DO (
SET "processed="
FOR /L %%a IN (0,1,!count!) DO (
IF "%%I"=="!cls[%%a]!" (SET /a clscnt[%%a]+=1&SET "processed=y")
)
IF not DEFINED processed SET /a count+=1&SET "cls[!count!]=%%I"&SET /a clscnt[!count!]=1
)
FOR /L %%a IN (0,1,%count%) DO ECHO !clscnt[%%a]! times !cls[%%a]!
ENDLOCAL
GOTO :EOF
I used a file named q58209698.txt containing some dummy data for my testing and chose to use the entire data line, having no suitable files where token 5 existed.
Note that as a bonus, I've added clscnt - an array of occurence-counts.
Shown: two separate ways of achieving the aim of finding/counting the unique tokens. Naturally, if the cls array is pre-loaded with the required tokens, then it's basic-programmer's-play to adjust the code to detect/report occurrences of those tokens.
The two methods are similar. In the first, set is used to list the established variables starting cls[. The first if ensures processing only the array-name cls, then either it's a repeat (set prcoessed to a value and increment the occurrences-counter) or it's a new value (when the for...%%a loop ends, processed is still undefined) so record it.
The second way is more direct, using the value of count to specifically interrogate the values in the cls array.
When I try iterating the folders with a for each approach I have no access to the current index and I've also failed to manually keep one:
#echo off
set "i=0"
set folders='dir /b /ad'
for /f "eol=: delims=" %%D in (%folders%) do (
:: echo %%D
echo %i%
set /a "i+=1"
)
When I try iterating with a fori approach based on this example I can't even get it working:
#echo off
cls
set "i=0"
:SymLoop
set folders='dir /b /ad'
if defined folders[%i%] (
echo %%folders[%i%]%%
set /a "i+=1"
GOTO :SymLoop
)
I'm aware of my total lack of knowledge on the topic so I'd appreciate any kind of correction and/or advice.
#ECHO OFF
SETLOCAL
#echo off
set /a i=0
set folders='dir /b /ad'
for /f "eol=: delims=" %%D in (%folders%) do (
REM echo %%D
CALL echo %%i%%
CALL SET "folders[%%i%%]=%%D"
set /a i+=1
)
SET fol
ECHO ---------------------------
#echo off
set /a i=0
:SymLoop
set folders='dir /b /ad'
if defined folders[%i%] (
CALL echo %%folders[%i%]%%
set /a "i+=1"
GOTO SymLoop
)
GOTO :EOF
Please refer to endless examples on SO about delayed expansion for simpler ways.
Not a good idea to use ::-comments within a (code block) as it can break the block.
set /a does not ordinarily require "quotes"
test_title.bat
:GET_DOWNLOADS
set Counter=-1
for /f "DELIMS=" %%i in ('type version.txt') do (
set /a Counter+=2
set "Line_!Counter!=%%i"
)
if exist version.txt del version.txt
exit /b
:list_files
call :GET_DOWNLOADS
For /L %%C in (1,2,%Counter%) Do (
:: removing this part makes it work fine
set line=%%C
set /a line+=1
set /a line/=2
:: alternate way doesnt work either
REM set /a line=%line% / 2
:: this part without the math part would be %%C instead of %Line%
echo %line%. !Line_%%C!
)
pause
(made an edit)
the second part isnt working for some reason
it just crashes
if i remove the line that does the math it works fine but instead display 1. 3. 5. 7.
version.txt
everything
0
minecraft
0
steam
0
obs
0
fixed test_list.bat :D
#echo off
setlocal enabledelayedexpansion
set "num=1"
set "counter=0"
for /f "DELIMS=" %%i in (version.txt) do (
set /a num+=1
if "!num!"=="2" (set /a counter+=1&set "line_!counter!=%%i"&set num=0)
)
echo.
For /L %%C in (1,1,%Counter%) Do (echo %%C. !Line_%%C!)
pause
#echo off
setlocal enabledelayedexpansion
set "num=1"
set "counter=0"
for /f "DELIMS=" %%i in (version.txt) do (
set /a num+=1
if "!num!"=="2" (set /a counter+=1&set "line_!counter!=%%i"&echo %%i&set num=0)
)
echo.
set line_1
set line_2
set line_3
pause
Would output:
everything
minecraft
steam
obs
line_1=everything
line_2=minecraft
line_3=steam
I'm trying to launch a random file with this software via a script - the only problem is that this script always selects the same random number on every launch. It's always 41 for me... Any suggestions?
#echo on
setlocal EnableDelayedExpansion
cd C:\Users\User\Documents\Downloads\Nintendo
set n=0
for %%f in (*.*) do (
set /A n+=1
set "file[!n!]=%%f"
)
set /A "rand=%random% * 100 / 32768+1"
"C:\Users\User\Downloads\fceux-2.2.2-win32\fceux.exe" "!file[%rand%]!"
That works for me:
#echo off
setlocal enabledelayedexpansion
c:
cd \windows
for %%f in (*.*) do (
set /A n+=1
set "file[!n!]=%%f"
)
rem change random seed value
for /l %%i in (0,1,%time:~-2%) do set /A tmp=!random!
set /A rand=!random! %% n-1
echo "!file[%rand%]!"
I have a batch file that is passed commands in the form of a string array from a Java file. The commands contain something like the following:
String[] commands = {"A",
"B",
"C",
"C:\users\user\Documents",
"C:\users\user\Pictures"}
The commands array is dynamic, as it changes every time the java program is run. In the batch file, I create variables to take the values of the first three elements (A, B, and C in this case). Then I need to shift the directory strings to take up the first three elements of the array. Here is the batch code I have so far:
#echo off
setlocal enableDelayedExpansion
set /A paramCount=0
for %%x in (%*) do (
set list[!paramCount!]=%%x
set /A paramCount=paramCount+1
)
set argA=%list[0]%
set argB=%list[1]%
set argC=%list[2]%
set /A old=0
set /A new=!old!+3
for /F "tokens=2 delims==" %%a in ('set list[') do (
echo old=!old!
echo new=!new!
set list[!old!]=!list[%new%]!
echo !list[%old%]!
set /A old=!old!+1
set /A new=!new!+1 )
The problem I am having is with the line set list[!old!]=!list[%new%]!. As you can see, I have delayed expansion enabled. However, the !!'s are needed for the list[...] variable that is emulating an element in an array. However, I believe I need to use delayed expansion for "new" as well. What am I to do in this case? Or perhaps that's not the actual problem? The "old" and "new" variables are incrementing correctly, but the echo !list[%old%]! line returns the same value every time. I expect the same issue exists in that line, with "old"--It should have !'s surrounding it but the !'s are already being used for the list[...] variable. So what happens if you need nested !'s in a statement? Thanks for the aid!
#echo off
setlocal ENABLEDELAYEDEXPANSION
set /A paramCount=-3
for %%x in (%*) do (
set list[!paramCount!]=%%x
set /A paramCount=paramCount+1
)
set argA=%list[-3]%
set argB=%list[-2]%
set argC=%list[-1]%
for /F "tokens=2 delims==" %%a in ('set list[-') do SET "%%a="
SET arg
SET list
ENDLOCAL
echo==================
setlocal ENABLEDELAYEDEXPANSION
set /A paramCount=0
for %%x in (%*) do (
set list[!paramCount!]=%%x
set /A paramCount=paramCount+1
)
set argA=%list[0]%
set argB=%list[1]%
set argC=%list[2]%
set /A old=0
set /A new=!old!+3
for /F "tokens=2 delims==" %%a in ('set list[') do (
echo old=!old!
echo new=!new!
CALL set list[%%old%%]=%%list[!new!]%%
CALL ECHO(%%list[!old!]%%
set /A old=!old!+1
set /A new=!new!+1
)
SET arg
SET list
GOTO :EOF
This should work for you - the easy way and the hard way.