Why isn't my BAT file variable being overwritten? - windows

I have this block of code:
#ECHO OFF
SET "SRCFOLDER=C:\Users\MyUserName\Desktop\PhotoTests"
SET "TEMPCODE=Hi"
ECHO %TEMPCODE%
ECHO.
FOR /F "tokens=*" %%G IN ('DIR /B %SRCFOLDER%') DO (
ECHO %%G
CALL tooltipInfo.bat %%G 19 | FIND /C "Star" > test.txt
SET /P TEMPCODE=<test.txt
ECHO %TEMPCODE%
ECHO.
)
SET /P TEMPCODE=<test.txt
ECHO %TEMPCODE%
ECHO.
PAUSE
I'm confused by the output as I noticed that the variable in the FOR loop is not overwritten by what I think should be the content of "test.txt", which will vary each time the FOR loop runs.
For the purpose of this example, the file tooltipInfo.bat will echo a text string like "1 Star" or "3 Stars" based on the rating recorded in the file's properties. The FIND statement should result in a "0" or "1" being saved into the test.txt file.
The output is:
Hi
Canon_Locked.JPG
Hi
Nikon_Locked.JPG
Hi
0
Press any key to continue . . .
May I know why the TEMPCODE variable isn't being overwritten in the loop and retains the original value of "Hi". However in the final block of code, it was able to read and echo out the actual content of the file.

This is a common mistake when using FOR and parentheses. The problem is that by default every variable between ( and ) is evaluated when the line is first read, and then re-used for each iteration of the FOR.
If the variable changes during the loop (via SET), then you will need to change % to ! for variables inside the parentheses, and also turn on delayed expansion using setlocal
SETLOCAL enabledelayedexpansion
FOR /F "tokens=*" %%G IN ('DIR /B %SRCFOLDER%') DO (
ECHO %%G
CALL tooltipInfo.bat %%G 19 | FIND /C "Star" > test.txt
SET /P TEMPCODE=<test.txt
ECHO !TEMPCODE!
ECHO.
)

Related

Take text from a text file and put each line into a variable

I have a problem taking a text file with 2 lines of text inside of it, and converting each line of the file into a separate variable.
I thought I could just repeat the same process for getting one line of text and just add skip=1 next to delims= and change the name of the variable it goes into, this did not work how I planned and I can't figure out another way to do it.
Here is my code:
#echo off
for /f "delims=" %%a in (file.txt) do (
set line1=%%a
)
for /f "skip=1 delims=" %%a in (file.txt) do (
set line2=%%a
)
echo %line1%
echo %line2%
pause
The text inside the file file.txt is this:
This is the Text on line 1
This is the Text on line 2
Instead of what i thought the output was going to be -
This is the Text on line 1
This is the Text on line 2
Press any key to continue...
It was this:
This is the Text on line 2
This is the Text on line 2
Press any key to continue...
It just prints the second line of the text file for both of the echos!
Please respond to this question as me not knowing how to do this is really bugging me
Thanks, Alex
This is a simple way:
#echo off
< file.txt ( set /P "line1=" & set /P "line2=" )
echo %line1%
echo %line2%
If you want to read more lines, or a variable number of lines, I suggest you to read Arrays, linked lists and other data structures in cmd.exe (batch) script
Take a look at this:
vars.txt (file with variables):
var1
var2
var3
tast.bat:
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET varFile=vars.txt
SET i=1
FOR /F %%l IN (%varFile%) DO (
SET line!i!=%%l
SET /a i=!i!+1
)
ECHO !line1!
ECHO !line3!
PAUSE
Output:
var1
var3
This will work regardless how many lines/variables you have. If you have only one, it will be stored in !line1!, if you have 1000, the 500th line will be stored in !line500! and so on.
This should work for lines with spaces by the help of tokens=*
#echo off
rem Creating env testing
(echo First blank line should be skiped
for /l %%i in (1,1,30) do ( echo This is the Text on line %%i)
)>_vars.tmp
setlocal enabledelayedexpansion
set i=1
for /F "skip=1 tokens=*" %%a in (_vars.tmp) do (
set line!i!=%%a
set /a i+=1
)
echo:!line1!
echo:!line3!
echo:!line30!
echo:!line100!
echo checking _vars.tmp
more _vars.tmp
del _vars.tmp
pause
exit /b 0

Result of each repeat of the loop to different file WIN BATCH

I would like to resolve simple problem - Saving to different file when loop repeats. I know im getting results because when I am doing >>file.txt
i am getting all restults into one file. It would be GREAT to save results to different files each time(and name this file by text from variable. but there is something wrong. It saves the results of last loop iteration.
#echo off
setlocal ENABLEDELAYEDEXPANSION
set vidx=0
for /F "tokens=1* delims=;" %%A in (list2.csv) do (
SET /A vidx=!vidx! + 1
set var!vidx!=%%A
rxrepl -f temp.txt -s "xNAMEx" -r "%%A">file___%var!vidx!%.txt
)
Try replacing this
file___%var!vidx!%.txt by this file___!var!!vidx!!!.txt
You don't need any variables to get the result you are looking for. Also, the * is usesless in "tokens=1*" if you never reference variable %%B. And "tokens=1" is the default. So all you need is:
for /F "delims=;" %%A in (list2.csv) do rxrepl -f temp.txt -s "xNAMEx" -r "%%A">"file___%%A.txt"
If you really want to build an "array" of var.N values, you can use FINDSTR to prefix each line with an incrementing number (line number).
for /F "tokens=1,2 delims=:;" %%A in ('findstr /n "^" list2.csv') do (
set "var.%%A=%%B"
set "var.cnt=%%A"
rxrepl -f temp.txt -s "xNAMEx" -r "%%B">"file___%%B.txt"
)
:: Display the "array" values
for /l %%N in (1 1 %var.cnt%) do echo var.%%N=!var.%%N!
Use just ...>"file___%%~A.txt" instead of erroneous >file___%var!vidx!%.txt
#ECHO OFF
SETLOCAL enableextensions enabledelayedexpansion
set vidx=0
for /F "tokens=1* delims=;" %%A in (list2.csv) do (
SET /A "vidx+=1"
set "var!vidx!=%%~A"
echo loopvar %%%% A=%%~A "file___%%~A.txt"
rem next line shows how to treat array-like names
call set "filenamepart=%%var!vidx!%%"
echo filenamepart=!filenamepart! "file___!filenamepart!.txt"
rem rxrepl -f temp.txt -s "xNAMEx" -r "%%A">"file___%%~A.txt"
)

Reading values in a text file and subsequent processing

A text file contains values. These values are to be used as an argument to an executable.
I tried the following to see how I can use inputs (line by line) from a file:
#echo off
for /f "tokens=*" %%i in (test.txt) do (
set n1=%%i
echo %n1%
echo "done"
)
test.txt contains numbers: Ex.
0.1
0.002
3
20
The output of the set of batch commands processed from a batch file is:
20
"done"
20
"done"
20
"done"
20
"done"
What went wrong here ?
To access variables inside a code block you need delayed expansion:
#ECHO OFF &SETLOCAL ENABLEDELAYEDEXPANSION
for /f "DELIMS=" %%i in (test.txt) do (
set "n1=%%~i"
echo !n1!
echo "done"
)
Please note: delayed expanded variables need exclams instead of percents.
In this part of code you do not need delayed expansion if you use the for loop parameter %%i as "variable":
#ECHO OFF &SETLOCAL
for /f "DELIMS=" %%i in (test.txt) do (
echo %%i
echo "done"
)
But you cannot make string conversion like set "n1=!n1:.0=.!" with %%i.

windows batch script - setting variable inside for loop

maybe i'm not representing my question clear, here's the actual code i did:
#echo off
set /p keywords="Enter keywords to search: " %=%
dir /b *.dat > filelist.txt
for /f "delims=." %%f in (filelist.txt) do (
for /f "delims= " %%g in (%%f.dat) do (
7z e %%g *sec.evtx
dir /b *.evtx > evtfile.txt
set /p tmpvar1=<evtfile.txt
del *.evtx
)
)
filelist.txt
tsnint1.dat
webint1.dat
tsnint1.dat
TSNINT1-201312091700.zip
TSNINT1-201312091600.zip
TSNINT1-201312091500.zip
TSNINT1-201312091400.zip
TSNINT1-201312091300.zip
TSNINT1-201312091200.zip
webint1.dat
WEBINT1-201312091300.zip
WEBINT1-201312091200.zip
the problem i'm facing is, evtfile consists of the right content but tmpvar1 is not assigned correctly as expected, what is my mistake and how to correct it? many thanks
You need delayed expansion to use a variable inside a block when this variable has been set (or changed) inside the same block. But you can set a variable without delayed expansion.
See this little demonstration (I used a simple if construct instead of for, but the effect is the same (not with if or for, but with blocks (inside ( and )).
#echo off
REM SETTING a variable inside a block
set "var=ONE"
echo start: %var%
if 1==1 (
echo inside block: %var%
set var=TWO
echo var has a new value:
set var
echo inside block is still old: %var%
)
echo after block: %var%
echo ----------
REM USING a variable inside a block
setlocal enabledelayedexpansion
set "var=ONE"
echo start: %var%
if 1==1 (
echo inside block: %var%
set var=TWO
echo var has a new value:
set var
echo new value inside block: !var!
echo just to demonstrate: %var%
)
echo after block: %var%
endlocal
echo ----------
echo working fine: %var%
echo not available after endlocal: !var!
This might help, using your code as a base. FWIW I hope that you have more than one copy of the .evtx files, if they are important to you.
#echo off
setocal enabledelayedexapnsion
for /f "delims=" %%f in ('dir /b *.dat') do (
for /f "delims=" %%g in ('type "%%f" ') do (
7z e "%%g" "*sec.evtx"
dir /b *.evtx > evtfile.txt
set /p tmpvar1=<evtfile.txt
echo !tempvar!
del *.evtx
)
)
One issue is that the *.evtx files are being deleted after the first archive is created, so the subsequent ones will have nothing to archive.

For loop statement in batch program repeats 5 times

But I'm still having an issue with regards to the program I posted previously. I think there is a problem in my for loop statement because after I opened the file "passwords.csv", I noticed that the loop repeated 5 times.
The first record R_000100.pdf was initially assigned the password 8337, but repeated in other rows and reassigned with other random passwords. And when I tried to open the PDF file, it seems that the last random password assigned (which is 13429) was really its password, and not 8337.
What should I do to correct the program wherein after the all the PDF files have been combined and assigned with passwords, the program will already stop the loop and exit? Thus having only one entry in the output file "passwords.csv" and won't repeat 5 times.
Below is the complete batch program I accomplished, with the help of Peter Wright.
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
for /f "tokens=1,2 delims=ABCDEF_." %%i in ('dir *.txt *.pdf /b') do (
TXTtoPDF A_%%i.txt A_%%i.pdf -pps4 -pfs10.9
TXTtoPDF B_%%i.txt B_%%i.pdf -pps4 -pfs8.9
TXTtoPDF C_%%i.txt C_%%i.pdf -pps4 -plm50 -prm50 -pfs7.9
TXTtoPDF D_%%i.txt D_%%i.pdf -pps4 -plm60 -prm60 -pfs8.9
TXTtoPDF E_%%i.txt E_%%i.pdf -pps5 -pot -pfs10
TXTtoPDF F_%%i.txt F_%%i.pdf -pps5 -pot -pfs12
set pass=!random!
pdftk *%%i.pdf cat output PDF\R_%%i.pdf user_pw !pass!
echo %%i R_%%i.pdf !pass! >> passwords.csv
)
echo ***************************************************
echo * *
echo * PDF REPORTS SUCCESSFULLY GENERATED. *
echo * PLEASE TYPE EXIT AT COMMAND PROMPT. *
echo * *
echo ***************************************************
pause
exit
Easy, what you have to do is give the batch file the logic to realise which line it is up to.
Replace :
for /f "tokens=1,2 delims=ABCDEF_." %%i in ('dir *.txt *.pdf /b') do (
With :
set /a count=0
for /f "tokens=1,2 delims=ABCDEF_." %%i in ('dir *.txt *.pdf /b') do (
set /a count+=1
if !count! equ 1 (
Note : add an extra bracket when closing the for-loop for the if-loop
This way, it will count each line the for-loop parse's. If you want to set your password for the second or fifth line, replace if !count! equ 1 ( with if !count! equ 2 ( or if !count! equ 5 ( respectively.
It is useful to do this in all batch files when using for-loops. It is done by default when using an actual programming language.
Hope this helped.
Yours Mona

Resources