If I simplified my requirement, I want to get last two digits of these strings using batch file. This is not the exact requirement. but I made it simple for understanding. :)
11-22-33
11-22-44
11-22-55
11-22-66
expected outcome is
33
44
55
66
This is the code I wrote
#echo off
SetLocal EnableDelayedExpansion
REM Fill strings to a array
set DIR_COUNT=0
for %%x in ("11-22-33" "11-22-44" "11-22-55" "11-22-66") do (
set /A DIR_COUNT+=1
set CONTENT_DIR_NAME=%%~x
set "DIR_LIST[!DIR_COUNT!]=!CONTENT_DIR_NAME!"
)
REM This part is working when I hard code the index of array to 1. I placed this two lines for testing purpose of above code.
for %%a in (%DIR_LIST[1]:-= %) do set mfgName=%%a
echo %mfgName%
REM this loop doesn't work because the syntax not correct.
for /L %%i in (1,1,%DIR_COUNT%) do (
for %%a in (%!DIR_LIST[%%i]!:-= %) do (
set mfgName=%%a
echo !mfgName!
)
)
As my understanding syntax of (%!DIR_LIST[%%i]!:-= %) is not correct. Any ideas how to DelayedExpansion inside a DelayedExpansion and correct this syntax
Here is the correct syntax for your batch file.
#echo off
SetLocal EnableDelayedExpansion
REM Fill strings to a array
set DIR_COUNT=0
for %%x in ("11-22-33" "11-22-44" "11-22-55" "11-22-66") do (
set /A DIR_COUNT+=1
set CONTENT_DIR_NAME=%%~x
set "DIR_LIST[!DIR_COUNT!]=!CONTENT_DIR_NAME!"
)
for /L %%i in (1,1,%DIR_COUNT%) do (
for %%a in (!DIR_LIST[%%i]:-^= !) do (
set mfgName=%%a
echo !mfgName!
)
)
pause
Related
I need to extract the characters of a string one by one in a loop. Ideally, I would've done something like this, but as you might have guessed, it doesn't work.
#echo off
setlocal EnableDelayedExpansion
set /a len=5
set var=abcde
for /l %%n in (1,1,%len%) do (
set /a num=%%n - 1
echo %var:~!num!,1%
)
it works seamlessly if I replace !num! with a plain number, but with the variable, behaves as if the percent signs aren't there and echoes:
var:~0,1
var:~1,1
var:~2,1
var:~3,1
var:~4,1
To directly fix your issue replace:
echo %var:~!num!,1%
with:
call echo %%var:~!num!,1%%`
But you can do it without set /a num=%%n - 1 because you are already counting using for /L but note we are counting from 0.
Also note, we start couting from 0.
#echo off
setlocal EnableDelayedExpansion
set /a len=4
set "var=abcde"
for /l %%n in (0,1,%len%) do (
echo(!var:~%%n,1!
)
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.
I'm new to Batch coding, so please go easy.
Please consider the following code:
FOR /L %%G IN (1,1,20) DO (break>"C:\New folder\%%G+1.txt")
I'm trying to create text files with the above code, but I'm getting 1+1, 2+1, 3+1.. and so on.
Is there a way to not touch the parameters, but to increase the parameter in %%G+1? Instead of outputting as a string, it gives me a number.
Please guide me. thanks
Update: I tried this code below
:MakeTextFiles
setlocal enabledelayedexpansion
set "var=1"
FOR /L %%G IN (1,1,20) DO
(
set /a "var=%var%+1"
break>"C:\New folder\!var!.txt"
)
EXIT /B
But it's not working.
setlocal enabldelayedexpansion
FOR /L %%G IN (1,1,20) DO
(
set /a _new=%%G+1
break>"C:\New folder\!_new!.txt"
)
Please see hundrds of articles on SO about delayedexpansion
Two problems with your latest change:
The ( must be on the same physical line as the do.
set /a var=!var!+1
or
set /a var=var+1
or
set /a var+=1
set /a accesses the run-time value of var, !var! is the run-time value of var, %var% is the parse-time value of var - the value that it has when the for is encountered.
You don't need arithmetic addition here, just change the set you loop over:
FOR /L %%G IN (2,1,21) DO (break>"C:\New folder\%%G.txt")
If you definitely want arithmetic:
setlocal enabledelayedexpansion
FOR /L %%G IN (1,1,20) DO (
set /a var=%%G+1
break>"C:\New folder\!var!.txt")
You need to look here:
calculating the sum of two variables in a batch script
and here
delayed expansion
I have a folder with 460 images with 23 per person in the format: image_0001.jpg to image_0460.jpg.
What is the batch command to rename them in the form 01-01.jpg to 01-23.jpg for a person and thus the entire database upto 20-23.jpg?
[EDIT]
I came across:
#echo off & setlocal EnableDelayedExpansion
set a=1
for /f "delims=" %%i in ('dir /b *') do (
if not "%%~nxi"=="%~nx0" (
ren "%%i" "!a!"
set /a a+=1
)
)
I could not find a way to use loop variables to do the same. Is there a way to use loop variables or is there another way?
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=U:\sourcedir"
SET /a filenum=10000
FOR /L %%a IN (1,1,20) DO (
FOR /L %%b IN (1,1,23) DO (
SET /a filenum+=1
SET /a newnum=10000+%%b+(%%a*100^)
ECHO(REN "%sourcedir%\image_!filenum:~-4!.jpg" "!newnum:~1,2!-!newnum:~-2!".jpg
)
)
GOTO :EOF
You would need to change the setting of sourcedir to suit your circumstances.
The required REN commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(REN to REN to actually rename the files.
The issue is one of leading zeroes, hence invoke delayedexpansion and calculate using 10000+a significant number, then substring.
The rest is simply a matter of mathematics.
This method use the % (modulus or remainder) operator to count in groups of 23: the image=(image+1)%23 part vary image variable from 0 to 22 and repeat this count. imgaux=101+image vary imgaux from 101 to 123 and just the last two digits are used in the ren command. Finally, person+=!image increment person variable each time that image is zero.
#echo off
setlocal EnableDelayedExpansion
set /A person=100, image=-1
for %%a in (*.jpg) do (
set /A "image=(image+1)%%23, imgaux=101+image, person+=^!image"
ECHO ren "%%a" "!person:~1!-!imgaux:~1!.jpg"
)
Note that in this method the number of persons doesn't need to be known in advance.
I have a batch file that contains the code below which assigns a variable for each line in a text file.
So the text file might have:
RELEASE1
RELEASE2
RELEASE3
The batch file sets each line in the text file to var1, var2, var3 with the following code:
#echo off
setlocal ENABLEDELAYEDEXPANSION
set vidx=0
for /F "tokens=*" %%A in (sites.txt) do (
SET /A vidx=!vidx! + 1
set var!vidx!=%%A
)
I need a method to echo all the defined variables. The number of variables will always change. So it might go up to var8 or var10 etc...
I'm pretty certain a for loop would do the trick but not sure what the best approach or how to do it? I was thinking of using vidx as the number of iterations? Thanks for your help!
Very Easy
#echo off
setlocal ENABLEDELAYEDEXPANSION
set count=0
for /F "tokens=*" %%A in (sites.txt) do (
SET /A count+= 1
set var!count!=%%A
)
Rem //:Notice That %count% still stores the last variable, use this in a "for /l" loop:
for /l %%a in (1,1,%count%) do (
Rem Below line is optional and displays variable number
<nul set /p="Variable %%a: "
Echo !var%%a!
)
That should work fine as long as none of the data contains parenthesis, in which case you'll have to escape them.
Type for /? for help on this. Ask If you want an explanation.
set var|findstr /R "var[0-9]*="
May be the shortest way....