Batch - set variable error; variable(%)(string)(%%a)(%)? - variables

On the batch script I'm currently working on, I've encountered a bit of a problem.
What I want to happen is to set a variable as itself, but after it to be followed by a percentage mark, a letter, a number from a for /l (#,#,#) loop, then another percentage sign.
My code is currently as follows;
set value1=1
set value2=10
for /l %%a in (%value1%,1,%value2%) do (
set variable1=%variable1%%b%%a%
)
This doesn't give me a value for %variable1% at all, even after looping this 10 times. I've tried adding 'variable1= ' (without apostrophes) to the top, however that gave me the same result. After searching around, I figured that I should try and cancel out the %'s which are before the 'b' and after the 'a' - using %'s in front of them -,and my code ended up like this;
set value1=1
set value2=10
set variable1=
for /l %%a in (%value1%,1,%value2%) do (
set variable1=%variable1%%b%%a%
)
This is the closest I got, however %variable1% would change the value to '%b1%', then '%b2%', then '%b3%', etc. Instead of tiling them up next to each other.
My desired result would be for, by the end of the loop, %variable1% to have a value of; %b1%%b2%%b3%%b4%%b5%%b6%%b7%%b8%%b9%%b10%
Where is my code going wrong? It seems that it should give me my desired output, however quite clearly, it's not.
Thanks in advanced,

Try this:
#echo off
setlocal EnableDelayedExpansion
set value1=1
set value2=10
set variable1=
for /l %%a in (!value1!,1,!value2!) do (
set percent=%%
set variable1=!variable1!!percent!b%%a!percent!
)
echo !variable1!
You will have to add setlocal EnableDelayedExpansion as this will helps to expand the variable at execution time rather than at parse time.

Related

for command to set a variable does not work

I'm running this command and I don't see why it won't work
setlocal EnableDelayedExpansion
for %%a in (harry-boy) do set %%a:-==
echo %harry%
pause
And this is the result I get -
e:\6\1>setlocal EnableDelayedExpansion
e:\6\1>for %a in (harry-boy) do set %a:-==
e:\6\1>set harry-boy:-==
e:\6\1>echo
ECHO is on.
e:\6\1>pause
Press any key to continue . . .
I'm changing the hyphen sign to a equals sign then running the set command on that. I expect to see that the variable "harry" = "boy"??
Here is a simple test -
set file=play=here.mkv
set %file:==-%
echo %file%
pause
and I get this -
set file=play=here.mkv
==-%
was unexpected at this time.
set %file:==-%
I thought I would get the new contents of file = play-here.mkv. Ok, I see that this makes the syntax wrong and the set command stops. So how do I change the = to a hyphen?
The string replacement format:
%var:old-string=new-string%
does NOT work on for replaceable parameters, just in Batch variables. The equivalent way for your example, using a variable instead, would be:
set a=harry-boy
set %a:-==%
echo %harry%
pause
Output:
C:>set a=harry-boy
C:>set harry=boy
C:>echo boy
boy
C:>pause
Press any key to continue . . .
Easy soloution:
for /f "tokens=1,2 delims=-" %%a in ("harry-boy") do set %%a=%%b
Echo %harry%
And that should do your job for you. But it will only work with one - in the quote.
SET will assign the value on the right of the first = to an environment variable named on the left.
Hence you would be assigning a value of = to a variable named harry-boy:- in BOTH cases.
You can verify this by executing
set harr
which will display any variable starting harr

Batch IF statement variable inside another variable

I'm having a problem with a framework for a batch game I'm trying to create. I want to check if a variable is something other than a blank space. However, which variable I'm trying to check is in itself defined by two variables. For example:
if not %px%xplayerlocation%y%yplayerlocation%%==%blank% goto wherever
As you can see, the variable to be checked is determined by the values of %xplayerlocation% and %yplayerlocation%. To my knowledge, only the outermost %% signs are being read as being a variable and the inner ones are being read as literal percent signs. Does anyone know a way around this problem? I'll give any additional information if anyone needs it. Thanks.
#ECHO OFF
SETLOCAL
SET "blank= "
SET xplayerlocation=3
SET yplayerlocation=4
ECHO test with blank================
SET px3y4=%blank%
CALL SET varval=%%px%xplayerlocation%y%yplayerlocation%%%
if not "%varval%"=="%blank%" ECHO goto wherever - NOT blank
ECHO test with "Q"================
SET px3y4=Q
CALL SET varval=%%px%xplayerlocation%y%yplayerlocation%%%
if not "%varval%"=="%blank%" ECHO goto wherever - NOT blank
GOTO :EOF
This should get you out of trouble.
You have recognized the source of the problem, but your description of the behavior is incorrect. The parser will attempt to expand variables named px and y, and it will convert the final %% into %.
The Magoo solution will work, but using CALL is quite slow. That may not be a problem for many small scripts, but for a batch game it can kill performance.
You want delayed expansion. Include setlocal enableDelayedExpansion near the beginning of your script. Then use the following:
if not !px%xplayerlocation%y%yplayerlocation%!==%blank% goto wherever
Normal %var% expansion occurs early at parse time, and !var! expansion occurs late at execution time, so you get the proper result.
The above will not work if the value of %blank% is a space. The simplest solution would be to use delayed expansion for !blank! as well.
You might find yourself in a situation where the coordinate values need to be set and expanded within the same block of code, like in a FOR loop or IF statement:
setlocal enableDelayedExpansion
...
REM This does not work
for ... in (...) do (
...
set /a "xPlayerLocation+=xChange, yPlayerLocation+=yChange"
if not !px%xplayerlocation%y%yplayerlocation%!==!blank! REM doSomething
...
)
The above will not work because %var% expansion occurs at parse time, and the entire parenthesized block of code is parsed before any code is executed. So the expanded value is constant - it will expand to the value that existed before the loop started.
The solution is to transfer the coordinate values to FOR variables using delayed expansion:
setlocal enableDelayedExpansion
...
REM This works
for ... in (...) do (
...
set /a "xPlayerLocation+=xChange, yPlayerLocation+=yChange"
for %%X in (!xPlayerLocation!) do for %%Y in (!yPlayerLocation!) do (
if not !px%%X%y%%Y!==%blank% REM doSomething
)
...
)
or
setlocal enableDelayedExpansion
...
REM This also works
for ... in (...) do (
...
set /a "xPlayerLocation+=xChange, yPlayerLocation+=yChange"
for /f "tokens=1,2" %%X in ("!xPlayerLocation! !yPlayerLocation!") do (
if not !px%%X%y%%Y!==%blank% REM doSomething
)
...
)
If you are serious about developing a high quality game using batch, then you may be interested in studying the techniques I used in developing SNAKE.BAT - an arcade style game using only native batch commands. The beginning of the post is a bunch of code, but afterwards I describe a number of techniques I used for improving performance. It is advanced stuff, so don't try to absorb everything at once. Absorb what you can, and then revisit the post later on after you gain more experience.

Removing spaces from a variable in batch

I am writing a file to remove spaces from filenames in a folder and then put the result in a .txt file. I just get a result of "Echo is on." over and over.
This is what I have so far:
#echo ON
SET LOCAL EnableDelayedExpansion
For %%# in (*.*) do (
SET var=%%~n#
Set MyVar=%var%
set MyVar=%MyVar: =%
echo %MyVar%>>text.txt
)
Can someone tell me whats wrong?
Removing all spaces (not just leading and trailing) can be done without using setlocal enabledelayedexpansionwith the following line:
set var=%var: =%
This works by replacing all spaces in the string with the empty string.
Source: DOS - String Manipulation
The reason why you are getting ECHO is on. is because delayed expansion was not used, which caused the value of %var% and %MyVar% to be inserted before the for command is run, and since they were not defined at the start, empty variables were inserted in. When the echo %MyVar%>>text.txt was run, it was interpreted as echo >>text.txt. When echo is run without any arguments, it outputs whether echo is on or off, which is what you get in text.txt.
To fix the problem, you have to do two things:
First, there is something wrong with your second line. There is no space between set and local in setlocal. The second line should be SETLOCAL EnableDelayedExpansion.
Second, to use delayed expansion, you have to replace all %s in each variable with !, like !var! instead of %var%.
End result:
#echo ON
SETLOCAL EnableDelayedExpansion
For %%# in (*.*) do (
SET var=%%~n#
Set MyVar=!var!
set MyVar=!MyVar: =!
echo !MyVar!>>text.txt
)
You actually do not need to use a temporary variable in this case, you can just do SET MyVar=%%~n# and skip to set MyVar=!MyVar: =!.
The wrong thing is you've enabled the variable expansion (you wroted it bad...) and also you are not using it, when you use enabledelayedexpansion you need to write the variable names as this: !Variable! instead of this else: %Variable%
But you don't need to use it with this code:
#echo ON
For %%# in (*) do (
SET "var=%%~n#"
Call Set "MyVar=%%var: =%%"
Call echo %%MyVar%%>>text.txt
)
Run the following batch in the folder holding the files to be renamed
#echo off
setlocal enabledelayedexpansion
for %%j in (*.*) do (
set filename=%%~nj
set filename=!filename=.=_!
set filename=!filename= =_!
if not "!filename!"=="%%~nj" ren "%%j" "!filename!%%~xj"
)
you just need to add the print to txt
The set var=%var: =% did not work for me.
So I tried with success for a number the following code:
set /a var-=1 & set /a var+=1

windows command line giving error on calculation

I found this nice little tidbit of code here: https://stackoverflow.com/a/5262637/2128987
#echo off
set starttime=%TIME%
set startcsec=%STARTTIME:~9,2%
set startsecs=%STARTTIME:~6,2%
set startmins=%STARTTIME:~3,2%
set starthour=%STARTTIME:~0,2%
set /a starttime=(%starthour%*60*60*100)+(%startmins%*60*100)+(%startsecs%*100)+(%startcsec%)
:TimeThis
robocopy /e /NFL /NDL /NJH /NJS /nc /ns /np folder%rndfolder% %drvltr%:\f%dirnew%\
set endtime=%time%
set endcsec=%endTIME:~9,2%
set endsecs=%endTIME:~6,2%
set endmins=%endTIME:~3,2%
set endhour=%endTIME:~0,2%
if %endhour% LSS %starthour% set /a endhour+=24
set /a endtime=(%endhour%*60*60*100)+(%endmins%*60*100)+(%endsecs%*100)+(%endcsec%)
set /a timetaken= ( %endtime% - %starttime% )
set /a timetakens= %timetaken% / 100
set timetaken=%timetakens%.%timetaken:~-2%
echo.
echo Took: %timetaken% sec.
As a standalone program it works great. I am using it with a robocopy command basically to determine how long it takes to write a file.
I add one extra variable in it because I want to keep the raw seconds for calculation purposes. So I add the extra line set timeraw=%timetaken%:
set /a timetaken= ( %endtime% - %starttime% )
***set timeraw=%timetaken%***
set /a timetakens= %timetaken% / 100
set timetaken=%timetakens%.%timetaken:~-2%
My batch file also uses setlocal enabledelayedexpansion
Well sometimes it does not properly calculate the "starttime" or "endtime". It's keeps it as the raw time in 08:30:22.35 type format and results in the error:
Invalid number. Numeric constants are either decimal (17),hexadecima (0x11), or octal (021)
Well obviously because it contains non-numeric characters like the : character.
My batch file goes in a continuous loop forever as I am using it to read, write, delete files and folders for a specific torture test condition.
Any idea why it would intermittently not calculate the starttime or endtime variables?
edit:
I made some changes to my overall script. I no longer need enabledelayedexpansion, cleaned up some if then statements, and simplified code a little. But I still occasionally get it where the starttime or endtime variables remain as the raw time format of HH:MM:SS.CS and causes error in calculation.
Old question, but there are probably blocks of parentheses and when you change a variable within parentheses then you need to use delayed expansion.
Run this and examine the differences.
#echo off
set a=nothing
if z==z (
set a=b
echo %a%
)
pause
setlocal enabledelayedexpansion
set a=nothing
if z==z (
set a=b
echo !a!
)
pause
Gee - a question nearly a year old, with no answer.
I'll assume that the problem has now been solved, so as a matter of record, I'd conclude that the
"sometimes it does not properly calculate" is because the hour/minute/second/hundredths will contain "08" or "09" which are not octal numbers.
The solution is
set /a startcsec=1%STARTTIME:~9,2% - 100
and repeat with each of the other 3 start time-segments; then repeat again with the end parts.
In addition, it could be that the hour is being presented with 0s suppressed. In this case, I'd suggest
set starttime=0%TIME: =%
set starttime=%startTIME:~-11%
set /a startcsec=1%STARTTIME:~9,2% - 100
where the first line prefixes the time with a '0', and replaces Space with [nothing]
the second selects just the last 11 characters of the result
and the last is the familiar form, using the resultant hh:mm:ss.cc format.
(obviously, the remainder of the substring-and-calculate method needs also to be implemented)

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.