Unable to echo user input values to file in Batch script - windows

I am writing a batch file that will generate/write to a property file based on multiple user input values. However, it is not recording the values of input. The result looks like
prop1=
prop2=
I wonder if there's something I need to know with set that is preventing this from working.
Weird part is that if I run this particular script multiple times, the value output from echo seems to be always be the user input from last time.
Code:
#echo off
IF NOT EXIST data_file (
set /p prop1=Enter value:
set /p prop2=Enter value:
(echo prop1=%prop1%) > data_file
(echo prop2=%prop2%) >> data_file
)

Classic problem for inexperienced batchers :)
%prop1% is expanded when the line is parsed. Your problem is that everthing within parentheses is parsed in one pass. So the value you see is the value that existed before you entered the IF statement.
You have two simple solutions.
1) Eliminate the enclosing parens by reversing the logic and using GOTO
#echo off
IF EXIST file goto skip
set /p prop1=Enter value:
set /p prop2=Enter value:
(echo prop1=%prop1%) >file
(echo prop2=%prop2%) >>file
:skip
2) Use delayed expansion - that takes place just before each line within the parens is executed
#echo off
setlocal enableDelayedExpansion
IF NOT EXIST file (
set /p prop1=Enter value:
set /p prop2=Enter value:
(echo prop1=!prop1!)>file
(echo prop2=!prop2!)>>file
)

You need to expand the variables using SETLOCAL ENABLEDELAYEDEXPANSION or use CALL.
#echo off
IF NOT EXIST data_file (
set /p prop1=Enter value:
set /p prop2=Enter value:
(
Call echo prop1=%%prop1%%
Call echo prop2=%%prop2%%
) > data_file
)

Related

Reference element by index in a list using Batch Script

Trying to obtain an element in a list by its index, using batch script. Here is the code:
#Echo off
setlocal EnableDelayedExpansion
set acc[0]=default
set acc[1]=Account_2
set acc[2]=Account_3
set acc[3]=Account_4
set acc[4]=Account_5
if exist interator.txt (
set /p i=<interator.txt
echo "read: !i!"
echo "!acc[%i%]!"
REM start cmd /c setx AWS_PROFILE !acc[%i%]!
REM start cmd /k python script.py
set /A i=i+1
(echo !i!)>interator.txt
echo "write: !i!"
) else (
(echo 0)>interator.txt
)
Output Received:
"read: 0"
""
"write: 1"
As setx requires the CMD session to be closed, for affect to take place. I am trying a different approach to automate some regular stuff.
Expected Output:
"read: 0"
"default"
"write: 1"
#Echo off
setlocal EnableDelayedExpansion
set "acc[0]=default
set "acc[1]=Account_2"
set "acc[2]=Account_3"
set "acc[3]=Account_4"
set "acc[4]=Account_5"
if exist q65771965.txt (
set /p i=<q65771965.txt
echo "read: !i!"
FOR %%a IN (acc[!i!]) DO (
ECHO "!%%a!"
echo start cmd /c setx AWS_PROFILE "!%%a!"
echo start cmd /k python script.py
)
set /A i=i+1
(echo !i!)
echo "write: !i!"
) else (
(echo 0)
)
GOTO :EOF
OK - small changes to allow this to work on my test environment:
Changed name of file from interator.txt to q65771965.txt (suits my environment)
Removed updating of data file so the modifications are shown on-screen.
Replaced REM start with ECHO start to show the start commands on-screen.
Subtle syntax-oriented change : Use set "var1=data" for setting values - this avoids problems caused by trailing spaces.
Significant change : insert a for loop to transfer indirect values to a metavariable (%%a) and use these.
Possibly-required : I don't use setx much, but I've some memory of the argument's needing to be "quoted"
The problem is, you used echo "%acc[!i!]%" within a codeblock. You need another layer of parsing, like call echo "%%acc[!i!]%%"
As an alternative, restructure your code, so the critical part isn't in a code block:
#Echo off
setlocal EnableDelayedExpansion
set acc[0]=default
set acc[1]=Account_2
set acc[2]=Account_3
set acc[3]=Account_4
set acc[4]=Account_5
if not exist interator.txt (
(echo 0)>interator.txt
goto :eof
)
set /p i=<interator.txt
echo "read: !i!"
echo "%acc[!i!]%"
set /A i=i+1
(echo !i!)>interator.txt
echo "write: !i!"
(this code is functionally identically to yours, just structured in another way)
(btw: it should probably iterator, not interator - but that's only spelling)

Batch file does not run unless first line is a variable assignment [duplicate]

I think I ran into a bug in Window's batch scripting.
I cannot set variables that are in an expanded if statement.
Here is an isolated part of my script:
#echo off
set success=1
set Version=12345
set Target=Client
set Type=456
set dir=
set zip=
if "%Version%"=="" set success=0
if "%Type%"=="" set success=0
if 1==1 set test=42
if %success%==1 (
set test2=57005
if "%Target%"=="Client" (
set dir=ModName v%Version%
set zip=ModName v%Version% %Type%.zip
echo Version: %Version%
echo Type: %Type%
echo.
echo Target: %Target%
echo dir: %dir%
echo zip: %zip%
echo.
echo test: %test%
echo test2: %test2%
)
) else (
echo Not successful.
)
This is the output from a brand new instance of cmd:
C:\Users\RandomClown\Desktop>test.bat
Version: 12345
Type: 456
Target: Client
dir:
zip:
test: 42
test2:
What you should notice is that the single line if statement correctly sets stuff.
The multiline if will perform anything that is NOT a set. I dont think I missed anything.
Also, the multiline if statement is correctly executing the right lines, as the else ( echo Not successful. ) lines did not execute.
Why did the lines not execute?
You missed something ;-)
cmd expands variables when commands are parsed, not when they are run. It so happens that an if or for statement with a block ( ... ) (or actually any block) counts as a single command in that case. So when you set variables inside a block and try using them in the same block there are no variables anymore – they were replaced by the values the variables had before the block even executed.
Stick a
setlocal enabledelayedexpansion
at the start of your batch file and use !zip! instead of %zip%. See help set for a detailed discussion of the problem.
Just a remind, the ms-dos "set" command takes every string after the equal sign. So if you write
if "x"=="x" set a=foo else set a=bar
echo %a% // output : foo else set a=bar
The %a% is actually set to "foo else set a=bar", not foo.
So I always use "()" for set command if there are multiple commands in one line.
if "%1"=="" (set a=20) else (set a=%1)

Cannot use !random! in batch file

#echo off
setlocal enableDelayedExpansion
set /p startIndex="Start index: "
set /p endIndex="End index: "
for /l %%a in (%startIndex% 1 %endIndex%) do (
set /a seed = !random!
echo %seed%
)
set /p endfile="Wait for it...."
I expect that this script will print out some random numbers. But it does not work. It just printed out some lines with same content: "Echo is off ."
How can I fix this code ?
You need to say
echo !seed!
because the whole loop is parsed at the beginning, and seed is expanded (to nothing, as it doesn't exist yet) before the loop starts running. You therefore need to use delayed expansion.
Delayed expansion is also required on referencing the value of variable seed defined and assigned with a random value within a block defined with ( ... ).
#echo off
setlocal EnableDelayedExpansion
set /p "startIndex=Start index: "
set /p "endIndex=End index: "
for /l %%a in (%startIndex% 1 %endIndex%) do (
set "seed=!random!"
echo !seed!
)
set /p "endfile=Wait for it ..."
Further option /a is not necessary to assign a random number to variable seed as no arithmetic expression to evaluate. But be careful with spaces around equal sign. All spaces are ignored by set on using option /a, but are not anymore ignored by command set on a simple assignment without option /a.
And also take care about where first double quote is written on line with command set as this makes a big difference.
For details about spaces around equal sign and first double quote position see answer on
Why is no string output with 'echo %var%' after using 'set var = text' on command line?

goto was not expected at this time batch

#echo off
:start
set string=
set lo=1
set a=0
set b=0
set cl=1
set cloop=
set google=0
set k=0
set r=0
set id=
set t=0
set f=0
set /p string=?
if defined string (
echo %string%
goto loop
) else (
echo please enter a string
goto start
)
:loop
set a=
for /f "tokens=%lo%" %%G IN ("%string%") DO echo %%G
if defined a (
echo %a%
set google=0
set /p cloop=<greetings.txt
pause
:cloop
set b=
for /f "tokens=%cl%" %%g IN ("%cloop%") DO set b=%%g
if defined string (
if %a%==%b% goto greetings
set /a cl=%cl%+1
goto cloop
) else (
set cl=0
set /a lo=%lo%+1
goto loop
)
) else (
goto google
)
:greetings
set f=0
set k=0
set r=0
set /p id=<greetingtone.dat
for /f "tokens=%cl%" %%g IN ("%id%") DO set t=%%g
start greeting.bat
call greeting.bat
goto talk
:google
echo not done yet
pause
goto start
i have narrowed it down to this line
if %a%==%b% goto greetings
when i remove it it runs
i have looked but i have no idea why it does not work
please help the greetings.txt has "hi hello grunt"
i think it might be the variables
If %a% or %b% are empty values, it is likely the compare is incomplete, and it is saying that the goto is not expected yet. For instance, if you type the following at a C:\ prompt:
c:\>if a== echo ok
c:\>if ==a echo ok
echo was unexpected at this time.
c:\>if == echo ok
ok was unexpected at this time.
c:\>
If you enclose each value in quotes, then the comparison will still work even if one or both of the values are empty. For instance:
if "%a%"=="%b%" goto greetings
The normal reason for that an unexpected word in an IF statement is that IF has a very specific syntax, IF item1 operator item2 actionstatement(s).
What is likely to be happening is that item1 AND item2 appear to be missing, so IF resolves that as IF == goto greetings. Since goto is not one of its known operators (==, equ, neq, leq, lss, geq, gtr`) then it complains.
The question from here is - why do %a% and %b% appear to be empty?
Within a block statement (a parenthesised series of statements), the entire block is parsed and then executed. Any %var% within the block will be replaced by that variable's value at the time the block is parsed - before the block is executed.
Hence, IF (something) else (somethingelse) will be executed using the values of %variables% at the time the IF is encountered. In your case, that means the outermost IF - in if defined string.
Two common ways to overcome this are 1) to use setlocal enabledelayedexpansion and use !var! in place of %var% to access the changed value of var or 2) to call a subroutine to perform further processing using the changed values.
Next problem is using a label within a block. Not a good idea. On some versions, a label will terminate the block. Call a subroutine instead.
call :cloop
...
goto start
:cloop
(whatever needs to be done)
goto :eof
(note that :cloop and :EOF have a required colon. on cloop it means "this is an internal subroutine - it's in the cuurrent batchfile." :EOF is a predefined label understood by CMD to mean end of file.)

What is wrong with this batch script?

I need a batch that reads a number from a file, increments it and saves it back into this file... This is what I came up with:
#ECHO OFF
SETLOCAL EnableDelayedExpansion
IF EXIST script\BUILDVERSION (
SET /p input = <script\BUILDVERSION
SET /a result=%input%+1
ECHO %result% > script\BUILDVERSION
) ELSE (
ECHO 0 > script\BUILDVERSION
)
At first it worked in a strange way, the result from reading the number from the file seemed to be a small random number, the result of the sum seemed random too... I don't know what I did, but now it doesn't even read the number from file into the variable...
Thanks in advance for help!
Instead of %input% and %result%, try using !input! and !result!. This seems to work better when using delayed expansion. Also, make sure you don't have any unnecessary spaces when reading from the file. You'll end up with:
#ECHO OFF
SETLOCAL EnableDelayedExpansion
IF EXIST script\BUILDVERSION (
SET /p input=<script\BUILDVERSION
SET /a result=!input!+1
ECHO !result! > script\BUILDVERSION
) ELSE (
ECHO 0 > script\BUILDVERSION
)

Resources