"SET"ing variable from other variable is not working - windows

I may be missing something or forgotten something but when I attempt to "SET" a variable within a batch file the value of another variable from a FOR loop, it does not work.
ECHO OFF
set /p inputfile="Enter the server list name: "
for /f %%z in (%inputfile%) do (
for /f "skip=1 tokens=1,2,3 delims=," %%a in (%%z.csv) do (
set inst=%%b
#echo Service Name: %%a
#echo %inst%
#echo Description: %%b
#echo Install Path: %%c
)
)
pause
My end goal is to replace the "\" present within the install path retrieved with "/" so that it will be compatible with a separate java app. During testing the variable "inst" comes back empty.
The syntax I am hoping to use is here: http://ss64.com/nt/syntax-replace.html
Any suggestions?

SET command works. What you need is Enable Delayed Expansion
Delayed Expansion will cause variables to be expanded at execution
time rather than at parse time, this option is turned on with the
SETLOCAL command. When delayed expansion is in effect variables may be
referenced using !variable_name! (in addition to the normal
%variable_name%)
ECHO OFF
SETLOCAL enableextensions enabledelayedexpansion
set /p "inputfile=Enter the server list name: "
for /f %%z in (%inputfile%) do (
for /f "skip=1 tokens=1,2* delims=," %%a in (%%z.csv) do (
set "inst=%%b"
#echo Service Name: %%a
#echo !inst! "!inst:\=/!"
#echo Description: %%b
#echo Install Path: %%c
)
)
pause

Brackets make multiple lines 1 line. Therefore you just need to move the echo's outside of the brackets so they are on a new line.
Variables are expanded when line is read. Therefore changes won't be noticed till the next line.
For multi command lines you can force expansion at execution time using !Var! syntax and turning this on with setlocal enabledelayedexpansion.
This is syntax to use to replace stuff set file=%windir:\=\\% replaces \ with \\ in %windir%

Related

Keep variable after endlocal in Batch

I have a folder structure, which is like for example C:\Temp\ and there are a lot of folder and file, and within each folder there are a "callme.bat". I would like to create a so called main.bat which is one after another call the callme files within the main' window. But there is a problem, within the callme files are some echo which contains "!" mark what make a problem for me.
I realized the problem with the setlocal-endlocal combo, because the batch scrip wants to interpret the message within the "!" marks, so I must use endlocal, but if I did I not able to run the callme bats.
callme.bat
#echo off
echo !!! hidden message !!! not hidden message
pause
main.bat variant 1
#echo off
setlocal enabledelayedexpansion
set PATH=C:\Temp
for /F %%x in ('dir /B/A:D %PATH%') do (
set CURR_DIR=%PATH%\%%x
set ACTUAL_BATCH=!CURR_DIR!\callme.bat
echo !ACTUAL_BATCH!
call !ACTUAL_BATCH!
pause
)
pause
exit
main.bat variant 2
#echo off
set PATH=C:\Temp
for /F %%x in ('dir /B/A:D %PATH%') do (
setlocal enabledelayedexpansion
set CURR_DIR=%PATH%\%%x
set ACTUAL_BATCH=!CURR_DIR!\callme.bat
echo !ACTUAL_BATCH!
ENDLOCAL & SET VAR=!ACTUAL_BATCH!
echo %VAR%
pause
)
pause
exit
main.bat variant 3
#echo off
set PATH=C:\Temp
for /F %%x in ('dir /B/A:D %PATH%') do (
setlocal enabledelayedexpansion
set CURR_DIR=%PATH%\%%x
set ACTUAL_BATCH=!CURR_DIR!\callme.bat
echo !ACTUAL_BATCH!
REM source: https://stackoverflow.com/questions/3262287/make-an-environment-variable-survive-endlocal
for /f "delims=" %%A in (""!ACTUAL_BATCH!"") do endlocal & set "VAR=%%~A"
echo %VAR%
call %VAR%
pause
)
pause
exit
So I don't know what to do. Anyone has an idea?
variant 1's output:
C:\Temp\1\callme.bat
not hidden message
C:\Temp\2\callme.bat
not hidden message
variant 2-3's output:
C:\Temp\1\callme.bat
ECHO is off.
C:\Temp\2\callme.bat
ECHO is off.
TL;DR
ENDLOCAL&set "varname=%sourcevarname%"
probably, where varname is the variablename to set and sourcevarname is the variable whose value is to be assigned to varname - and they CAN be the same name, even if the statement appears logically null - it's exporting the variable from within the setlocal/endlocal block.
Key point: MUST be on one physical line and may be repeated if necessary (ie
ENDLOCAL&set "varname=%sourcevarname%"&set "varname2=%sourcevarname2%"
So
ENDLOCAL&set "fred=%fred%"&set "bill=%george%"
is perfectly valid, to set the value of fred outside the setlocal/endlocal bracket to its final value inside and of billoutside to the final value of george inside.
Some points about your code:
Never use PATH as a variable name, as it destroys the PATH variable for searching executable files.
Use the extended SET syntax set "varname=content" to avoid problems with trainling spaces.
You only need to disable the delayed expansion mode by using setlocal DisableDelayedExpansion
#echo off
setlocal EnableDelayedExpansion
set MY_PATH=C:\Temp
for /F %%x in ('dir /B/A:D %PATH%') do (
set "CURR_DIR=%MY_PATH%\%%x"
set "ACTUAL_BATCH=!CURR_DIR!\callme.bat"
call :execute ACTUAL_BATCH
pause
)
pause
exit /b
:execute ACTUAL_BATCH
set "batFile=!%~1!"
echo Calling !batFile!
setlocal DisableDelayedExpansion
call %batFile%
endlocal
exit /b

How to read a string with "!" from a file in windows batch script?

I'm writing a batch script to read from a file. The file contains lines such as token=value. I have code to parse each line of the file and it is stored in %%i. The following code tries to extract the value of token:
Take note that this script is using delayed expansion, as mentioned in the comments.
for /f "tokens=1* delims==" %%a in ("%%i") do (
if "%%a"=="password" ( set password=%%b )
)
If value of token password contains "!", then the "!" is skipped and only rest of the string is stored in variable password. Example, if the line is:
password=Test!
then variable password=Test . I have tried to change the input file various ways and batch script reads everything except "!". I have used:
password="Test!"
password="Test^!"
password=Test%!
password=Test%!
and everything skips "!". Any idea how I can read a string with "!" into a variable?
Assuming you're using delayed variable expansion just disable it temporarily for the comparison. To compare in the non-delayed mode I'd parse the current line splitting by ! and check if the first token is the same as the entire line:
#echo off
setlocal enableDelayedExpansion
for /f "delims=" %%i in (sourcefile.txt) do (
setlocal disableDelayedExpansion
for /f "delims=! tokens=1" %%z in ("%%i") do (
if "%%z"=="%%i" ( rem The line has no !
for /f "tokens=1* delims==" %%a in ("%%i") do (
if "%%a"=="password" ( set "password=%%b" )
)
)
)
endlocal
)
pause
However password variable will be only available in the inner setlocal context, to export it use that answer.
I am not experiencing that problem with the code you posted. I think the error may precede the code you posted which stores each line of the file in %%i.
Put an echo statement in there before your %%a loop so that you can verify the contents of %%i before processing further. I highly suspect that the exclamation point isn't making it into %%i in the first place.
Here is the full CMD file I ran on Windows 7:
#echo off
for /f "tokens=1* delims= " %%i in ("password=Test!") do (
echo i: %%i
for /f "tokens=1* delims==" %%a in ("%%i") do (
if "%%a"=="password" ( set password=%%b )
)
)
echo password: %password%
The output is as follows:
i: password=Test!
password: Test!
So you can see that Test! is making it through the for loop intact when %%i contains password=Test!. If you want to post the earlier pieces of your batch file, we can help you troubleshoot further.

Why is variable not redefined with each iteration of for loop batch script?

I have this issue where I want to re-define a variable with each iteration of a for loop. I cannot figure out why this is not working. I have tried messing with enabledelayedexpansion but have not had success.
echo off
for /f "tokens=1-7 delims=::/ " %%A in ("%DATE% %TIME%") do set capture_time=%%D-%%B-%%C_%%E%%F%%G
for /l %%a in (1,1,3) do (
echo %capture_time%
timeout 3 /nobreak
for /f "tokens=1-7 delims=::/ " %%A in ("%DATE% %TIME%") do set capture_time=%%D-%%B-%%C_%%E%%F%%G
)
My desired output would be something like this:
2015-08-27_132506.50
2015-08-27_132509.50
2015-08-27_132512.50
Where each time the loop is run, the capture_time is updated.
Every environment variable within a block defined with ( and ) and referenced with %Variable Name% is expanded already by command processor on parsing the block. This can be seen on running a batch file from within a command prompt window with using echo on or having #echo off removed or commented out with rem.
The solution is using delayed expansion as demonstrated below.
#echo off
setlocal EnableDelayedExpansion
for /f "tokens=1-7 delims=::/ " %%A in ("%DATE% %TIME%") do set "capture_time=%%D-%%B-%%C_%%E%%F%%G"
for /l %%a in (1,1,3) do (
echo !capture_time!
timeout 3 /nobreak
for /f "tokens=1-7 delims=::/ " %%A in ("!DATE! !TIME!") do set "capture_time=%%D-%%B-%%C_%%E%%F%%G"
)
endlocal
For more details on delayed expansion open a command prompt window, execute there set /? and read all help pages output into the command prompt window carefully. Delayed expansion is explained in help on an example.
Why it is always better to use set "variable=value" instead of set variable=value is explained for example here.

Using Windows Batch Script Can I Use A For Loop To Iterate Multi-Line File And Run Multiple Commands

I would like to iterate a flat text file containing a Windows directory listing and run multiple commands against each line assigning each line to a variable. I then want to echo each resulting output from each command into a comma-delimited file. Yes, I understand batch programming might not be the best choice but am somewhat limited at the moment. Here is where I am at with it:
#echo off
setlocal
SETLOCAL ENABLEDELAYEDEXPANSION
:: There could be spaces in the filename, thus using delims
FOR /f "delims=?" %%a in (e:\multiline_textfile.txt) do (
set filename=%%a
CALL :PROG1
CALL :PROG2
CALL :PROG3
CALL :ENDPROG
:PROG1
FOR /f "delims=?" %%h in ('e:\apps\exe1.exe -s "!filename!"') do set result11=%%h
:PROG2
FOR /f "delims=?" %%i in ('e:\apps\exe1.exe -b"!filename!"') do set result2=%%i
:PROG3
FOR /f "delims=?" %%j in ('e:\apps\exe2.exe -c "!filename!"') do set result3=%%j
:ENDPROG
echo !result1!,!result2!,!result3!
)
---
Any insight would be greatly appreciated.
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
:: There could be spaces in the filename, thus using delims
FOR /f "delims=" %%a in (e:\multiline_textfile.txt) do (
set "filename=%%a"
CALL :PROG1
CALL :PROG2
CALL :PROG3
CALL :ENDPROG
)
echo here endeth your batch mainline
goto :eof
:PROG1
FOR /f "delims=" %%h in ('e:\apps\exe1.exe -s "!filename!"') do set "result1=%%h"
goto :eof
:PROG2
FOR /f "delims=" %%i in ('e:\apps\exe1.exe -b"!filename!"') do set "result2=%%i"
goto :eof
:PROG3
FOR /f "delims=" %%j in ('e:\apps\exe2.exe -c "!filename!"') do set "result3=%%j"
goto :eof
:ENDPROG
echo !result1!,!result2!,!result3!
goto :eof
You don't need the initial SETLOCAL - one is quite sufficient.
Labels are simply MARKERS in a batch program - they don't affect flow. The most common way to return in a CALLed routine is to GOTO :EOF where the colon is REQUIRED and the label :EOF is implicit and should NOT be declared.
Bad idea to attempt to use labels within a FOR loop like that. Might work with later versions, but not with earlier. Note the FOR loop's ending ) has been moved...
Whereas !var! works, it is not necessary in this case because each subroutine is essentially a whole new program which inherits the main environment as it stood at the CALL. Hence each !var! could be replaced by %var% and the SETLOCAL ENABLEDELAYEDEXPANSION need only be a SETLOCAL. You only need to use delayedexpansion where an ordinary environment variable's value is to be used after being changed in a compound statement (like a FOR over multiple lines, for instance)

Store Multiline String in Batch Variable

I need to remove a string that may occur inside a file. The string has many lines. Can I perform this action using a Batch script?
I've heard that you cant have variables with more than one line in Batch? The string will come from another file that I will read into a variable using Batch.
The following code seems to only store the 1st/last line of a file in the string?? Whats going wrong?
Rem Read file and store all contents in string
Set replace=
Set target=
Set OUTFILE=res.txt
for /f "delims=" %%i in (myFile.txt) do set target=%target% %%i
echo %target%
Rem When I print target I only have one line not many lines?? Whats going wrong
Rem Remove the target string from myOtherFile.txt: this code is from http://stackoverflow.com/questions/5273937/how-to-replace-substrings-in-windows-batch-file
for /f "tokens=1,* delims=ΒΆ" %%A in ( '"type myOtherFile.txt"') do (
SET string=%%A
SET modified=!string:%target%=%replace%!
echo !modified! >> %OUTFILE%
)
Try this:
#echo off &setlocal enabledelayedexpansion
for /f "delims=" %%i in (myFile.txt) do set "target=!target! %%i"
echo %target%
Inside a code block you need always delayed expansion for variables with variable values.
Try this, change last to:
echo !target!

Resources