Unset variable value assigned within if statement inside a nested for loop - batch-file

I am trying to make one batch file to read parameters from the file and pass it to ant for deployment.
I have made the below batch file:
setlocal enabledelayedexpansion
echo on
IF EXIST "D:\testfile1.txt" (
echo Do one thing
set string=
set /p string=< D:\testfile1.txt
echo value taken from file is %string
for /f "tokens=2,4,6 delims==:" %%G IN ("%string%") DO (
echo %%G %%H %%I
set env=%%G
set dom=%%H
set com=%%I
echo ENV !env!
echo DOM !dom!
echo COM !com!
cd D:\kpn_eai\EAI_FIXED\branches\kpn_eai_fixed\fixed\build\scripts
%ANT_HOME%\bin\xanteai deploy %%G %%H %%I
)
) ELSE (
echo Do another thing
)
endlocal
In testfile1.txt I have parameters in below format:
Environment=Env_Name1:Domain=Domain_Name1:Component=Component_name1
Parameters are different deployments. When I am running the above code it is giving below output
D:\>echo off
Do one thing Ant home is C:\tibco\ant\apache-ant-1.9.13
value taken from file is Environment=Env_name1:Domain=Domain_Name1:Component=Component_name1
Env_name1 Domain_Name1 Component_name1
ENV Env_name1
DOM Domain_Name1
COM Component_name1
Deployments starts after this.
The issue I am facing is when I run this code for different parameters (in testfile1.txt) the values of ENV, DOM and COM remains same regardless of any parameters read from testfile1.txt.
Can anyone help me to correct this code and let me know how can I just assign the values read from file to a variable and pass it to ant for deployment?
NOTE:- This batch file will be placed in scheduler which will check for testfile1.txt after every 5 minutes, when it finds that file deployment process gets triggered. Thus I have included if condition to check availability of file.

There really shouldn't be any need to be setting or echoing everything as you go, so why not just do something like this instead:
#Echo Off
If Exist "testfile1.txt" (Set /P "string="<"testfile1.txt"
SetLocal EnableDelayedExpansion
Echo value taken from file is !string!
For /F "Tokens=2,4,6 Delims==:" %%A In ("!string!") Do (
CD /D "D:\kpn_eai\EAI_FIXED\branches\kpn_eai_fixed\fixed\build\scripts"
"%ANT_HOME%\bin\xanteai" deploy %%A %%B %%C)
EndLocal) Else Echo Do another thing

You could first split the read line at the colons with a simple for and
obtain the variable names env,dom,com from the content.
Here preceeded with an underscore for easier output.
:: Q:\Test\2019\03\08\SO_55061545_.cmd
#echo off
setlocal enabledelayedexpansion
set "FileIn=D:\testfile1.txt"
IF not EXIST "%FileIn%" (
echo Do another thing
Goto :somewhere
)
echo Do one thing
set "string="
set /p "string="<"%FileIn%"
echo value taken from file is %string%
for %%A in ("%string::=" "%") do for /f "tokens=1* delims==" %%B IN ("%%~A") DO (
echo %%A %%B %%C
set var=%%B
set "_!var:~0,3!=%%C"
)
set _
:: cd D:\kpn_eai\EAI_FIXED\branches\kpn_eai_fixed\fixed\build\scripts
:: %ANT_HOME%\bin\xanteai deploy %_env% %_dom% %_com%
endlocal
:somewhere
> SO_55061545_.cmd
Do one thing
value taken from file is Environment=Env_Name1:Domain=Domain_Name1:Component=Component_name1
"Environment=Env_Name1" Environment Env_Name1
"Domain=Domain_Name1" Domain Domain_Name1
"Component=Component_name1" Component Component_name1
_Com=Component_name1
_Dom=Domain_Name1
_Env=Env_Name1

Related

Using a batch script, how do I count files in a remote folder using a ip list/reference file and output it in a ip + filecount format?

What I want to achieve is have an output file that lists how many files are in a specific folder on a number of different remote machines ie(127.0.0.1 394files).
The issue I'm having is the output file generated only has 1 line in it, the last IP in ip.txt
To try and explain the code below, I'm creating a variable called 'testip' which should match the ip/machine I'm calling from ip.txt , this is created purely for the echo at the end, when I tried calling %%i or %%b at an echo, all that appears in the text file is %i or %b , as if its truncating 1 of the % characters. creating a separate variable (SET testip=%%b) got around that issue.
Next loop, it looks for the IP list in the ip.txt file and performs a count on the \test_scripts\ folder.
Then it should echo the IP it ran as well as the count number.
Any idea where this is going wrong?
Any feedback appreciated.
#ECHO OFF
SETLOCAL
SETLOCAL ENABLEDELAYEDEXPANSION
for /f "delims=" %%b in (' type "C:\Users\testuser\Desktop\test_scripts\ip.txt" ' ) DO SET testip=%%b
for /f "delims=" %%i in (' type "C:\Users\testuser\Desktop\test_scripts\ip.txt" ' ) DO (
SET count=0
for %%o IN ('type "\\%%i\c$\Users\testuser\Desktop\test_scripts\*.*" ' ) DO (
SET /A count=count + 1
)
)
echo %testip% %count% >> output.txt
ENDLOCAL ENABLEDELAYEDEXPANSION
ENDLOCAL
Try this one instead. Note how delayed expansion is used. For more on the commands, run them with /? switch on cmdline. for instance. for /?
Also you will see that command type is not used at all.
#echo off
setlocal enabledelayedexpansion
set "location=C:\Users\testuser\Desktop\test_scripts\ip.txt"
for /f "delims=" %%i in (%location%) DO (
set "remote=\\%%i\c$\Users\testuser\Desktop\test_scripts\*"
set count=0
for %%x in (!remote!) do set /a count+=1
echo !remote! !count! >> output.txt
)
This is the same method as Gerhards answer but with two modifications. I've set the remote variable at the start of the script instead of repeating that on each iteration of the loop; and I'm outputting the IP address, instead of the remote path, with the file count.
#Echo Off
SetLocal EnableDelayedExpansion
Set "location=%UserProfile%\Desktop\test_scripts\ip.txt"
Set "remote=\\%%A\C$\Users\testuser\Desktop\test_scripts"
( For /F "Usebackq Delims=" %%A In ("%location%") Do (Set "#=0"
For %%B In ("%remote%\*") Do Set /A #+=1
Echo %%A !#!))>"output.txt"
This is similar except that it uses the Dir command to retrieve the file count. The Dir command can take account of hidden and system files etc.
#Echo Off
SetLocal EnableDelayedExpansion
Set "location=%UserProfile%\Desktop\test_scripts\ip.txt"
Set "remote=\\%%A\C$\Users\testuser\Desktop\test_scripts"
( For /F "Usebackq Delims=" %%A In ("%location%") Do (Set "_=" & Set "#="
For /F %%B In ('Dir "%remote%" /A-D/D') Do Set "#=!_!" & Set "_=%%B"
Echo %%A !#!))>"output.txt"
You can easily modify your location and remote paths on lines 3 and 4, ensuring that the \\%%A\ section remains unaltered.
In have not tested either script, nor have I made any attempt at error trapping etc. I'll leave that to you, should it be required.

Environment variable value not set, but why?

Why is batch variable TESTTYPE not passed through to the calling batch file (Windows 7 machine)?
I trigger a test system via SVN commit message. Given e.g. this SVN message:
This should trigger my test system for a long test.
testing RunTest#longtest
Problem: The command set at the end of the inner batch file properly outputs longtest but the outer batch file outputs smoketest unexpectedly.
This is the calling batch file test.bat:
call %~dp0gettype.bat trunk 12345
echo %TESTTYPE%
This is the called batch file gettype.bat doing the work:
set TESTTYPE=smoketest
::find all lines in the string which contain the keyword "RunTest#"
setlocal EnableDelayedExpansion
set "cmd=svn log -r %2 -v | findstr /r "RunTest#""
::for all words in that found line call the subroutine "handleElement"
for /F "tokens=*" %%a in ('!cmd!') do (
if "%%a" NEQ "" for %%b in (%%a) do call:handleElement %%b
)
goto ende
::split on hashtag char and handle the keyword after the hashtag (and find the type)
:handleElement
set TMPSTR=%1
set TAGNAME=%TMPSTR:~0,8%
if "%TAGNAME%"=="RunTest#" call:getSpecialType %TMPSTR:~8%
goto:eof
:getSpecialType
set TESTTYPE=%1
goto:eof
:ende
set
change
call %~dp0gettype.bat
echo %TESTTYPE%
to
for /F "usebackq" %%i in (`call %~dp0gettype.bat`) do set "TESTTYPE=%%i"
echo %TESTTYPE%
and in gettype.bat
change
:ende
set
to
:ende
echo %TESTTYPE%

Updating a variable in a batch file

I have done some researching on this topic but everything I have tried doesn't work properly. I just want to add a counter to certain aspects of my batch file. The count.txt file contains:
Counters started on 2-18-15
opened: 0
actions: 0
The script that I have written so far is:
setlocal enabledelayedexpansion
for /F "usebackq tokens=2" %%r in (`findstr opened: counter.txt`) do (
echo %%r
set opened=%%r
set /a opened=!opened!+1
echo opened= !opened!
)
I would like to just edit the number of opened times and not change anything else in the file. I know this is rememdial but I am still very remedial in my batch abilities.
I have specified ! in place of %, using some debugging it is pulling the correct variable and adding 1 to it, the current issue is that it is not saving over that variable afterwards.
You need to use delayed expansion to properly display variables set inside of code blocks.
setlocal enabledelayedexpansion
for /F "usebackq tokens=2" %%r in (`findstr /C:"opened:" counter.txt`) do (
set opened=%%r
set /a opened=!opened!+1
echo opened=!opened!
)
You never write the information back to the file - you are simply echoing the value to the screen.
Batch does not have a mechanism to modify a value in a file directly. You must write a new file with the updated information, and then replace the old file with the new.
Assuming the order of the lines does not matter, I would write a batch script as follows:
#echo off
setlocal
for /f "tokens=2" %%N in ('findstr /bc:"opened: " counter.txt') do set /a opened=%%N+1
>counter.txt.new (
findstr /vbc:"opened: " counter.txt
echo opened: %opened%
)
move /y counter.txt.new counter.txt >nul
After running the script once, your counter.txt file would look like:
Counters started on 2-18-15
actions: 0
opened: 1
You might want to preserve the order of the rows. You could do so with a pure batch script, but I rarely use batch to modify text files. Instead, I would use my JREPL.BAT utility - it is faster, more reliable, and simpler (assuming you understand regular expressions and rudimentary JScript)
call jrepl "^(opened:\s*)(\d+)$" "$1+(Number($2)+1)" /j /f test.txt /o -
#ECHO OFF
SETLOCAL
(
for /F "delims=" %%a in (q28585447.txt) do (
for /F "tokens=1,2" %%q in ("%%a") do (
IF "%%q"=="opened:" (CALL :REPLACE %%r) ELSE (ECHO %%a)
)
)
)>newfile.txt
GOTO :EOF
:REPLACE
SET /a newvalue=%1+1
ECHO(opened: %newvalue%
GOTO :eof
I used a file named q28585447.txt containing your data for my testing.
Produces newfile.txt To replace your file, use move /y newfile.txt q28585447.txt (after modifying throughout for your filename, of course.
Simply, it reads each line from the data file to %%a then tokenises %%a using the default separators into %%q and %%r If %%q is the target string, then %%r contains the value to be incremented, otherwise regurgitate the line in %%a.
The subroutine :replace simlpy adds 1 to the parameter passed and reconstructs the target line.
By surrounding the entire for...%%a loop in parentheses and redirecting to a file, all of the output echoed is redirected to that file.

Batch File - loop incrementing count in value not displaying correctly

I'm trying to read a file and output the lines of data into registry keys. The data collection works, but I don't understand the syntax required to increment the string values in the last loop.
#echo OFF
SETLOCAL DisableDelayedExpansion
FOR /F "usebackq skip=1 delims=" %%a in (`"findstr /n ^^ C:\GetSID.txt"`) do (
set "var=%%a"
SETLOCAL EnableDelayedExpansion
set "var=!var:*:=!" This removes the prefix
echo(!var:~76,63!>>C:\SIDoutput.txt
goto :EndLoop
)
:EndLoop
set /p SID= <C:\users\paintic\SIDoutput.txt
set KEY_NAME="HKEY_USERS\!SID!\Software\Microsoft\Windows NT\CurrentVersion\PrinterPorts"
set Counter=1
for /f %%x in (C:\users\paintic\Networkprinters.txt) do (
set "Line_!Counter!=%%x"
set /a Counter+=1
if !Counter!==3 (Echo %line_counter%)
)
set /a counter2=!counter!-3
set counter=1
The part below is what I can't get to work. I'm trying to write LINE_1, LINE_2 and LINE_3 values from the previous loop to increment via the loop below. So VALUENAME should equal LINE_1, TYPE should = LINE_2's value and DATA should = LINE_3 on the first run and keep going up by 1 until the loop finishes (end of the file read)
`for /L %%i in (1,1,%counter2%) do (
set ValueName=%Line_!counter!%
set /a counter+=1
set Type=%Line_!counter!%
set /a Counter+=1
set Data=%Line_!counter!%
set /a Counter+=1
echo !ValueName!
echo !Type!
echo !Data!
REG ADD %KEY_NAME% /v !ValueName! /t !Type! /d !Data! /f
)
ENDLOCAL
Pause`
On searching for errors in batch file it is always helpful to use in first line #echo on or remove #echo off or comment this line with rem to see what cmd.exe really executes.
Command line interpreter fails on lines with set VariableName=%Line_!counter!% as the interpreter does not know what to expand first. I think it is not possible to create dynamically the name of an environment variable and reference next the value of this environment variable. This approach most likely does not work ever.
However, what you want to achieve can be done much easier directly in second loop as the following example demonstrates:
#echo off
setlocal EnableDelayedExpansion
rem Create data for demo example.
set "KEY_NAME=HKEY_USERS\S-1-5-20\Software\Microsoft\Windows NT\CurrentVersion\PrinterPorts"
echo TestValue>"%TEMP%\Networkprinters.txt"
echo REG_SZ>>"%TEMP%\Networkprinters.txt"
echo Sample Data>>"%TEMP%\Networkprinters.txt"
echo AnotherValue>>"%TEMP%\Networkprinters.txt"
echo REG_DWORD>>"%TEMP%\Networkprinters.txt"
echo ^1>>"%TEMP%\Networkprinters.txt"
rem Now the loop follows which reads the data from the file line
rem by line and build the line for using command "reg.exe" to
rem add the data to registry of the user with the defined SID.
set Counter=1
for /f "usebackq delims=" %%x in ("%TEMP%\Networkprinters.txt") do (
if "!Counter!"=="1" (
set "ValueName=%%x"
) else if "!Counter!"=="2" (
set "ValueType=%%x"
) else (
set "ValueData=%%x"
rem Echo the command instead of really executing "reg.exe".
echo reg.exe ADD %KEY_NAME% /v "!ValueName!" /t !ValueType! /d "!ValueData!" /f
set Counter=0
)
set /a Counter+=1
)
rem Delete the text file created for demo example.
del "%TEMP%\Networkprinters.txt"
endlocal
This solution is much easier than what you have tried and can be maybe even more simplified.

batch: get last folder name from path from txt

i need take paths from txt and get last folder name and then use it.
setlocal EnableDelayedExpansion
set InputFile=somar.txt
for /f "tokens=* delims=" %%x in ('Type "%InputFile%"') do (
set path=%%x
:shift
for /f "tokens=1* delims=\/" %%i in ( "!path!" ) do (
set folder=%%i
set path=%%j
)
if not [!path!] == [] goto :shift
echo folder: !folder!
)
endlocal
problem is that it works only for first line in txt. where is the problem?
You have a number of problems:
1) Your FOR loop is broken the moment you issue a GOTO. You will not get any more FOR loop iterations after GOTO. You could fix this by moving your GOTO loop into a subroutine and then CALL the subroutine from within your DO loop.
2) The PATH environment variable has a reserved meaning for Windows. You should never use that variable name for your own purposes, even if it is localized as you have it. It isn't worth tempting fate. Simply use a different variable name.
3) Perhaps not an issue with your data, but ! is a valid character for a file or folder name. Your expansion of FOR variables will corrupt names containing ! if delayed expansion is enabled. This can be fixed by toggling delayed expansion on and off as needed.
You also have a minor inefficiency - There is no need to use TYPE with your FOR loop. You can simply let FOR read the file directly. (unless the file is unicode)
You could take all the recommendations above, but there is a much simpler solution :-)
EDIT - change made to handle a path that ends with \
#echo off
set "InputFile=somar.txt"
for /f "usebackq eol=: delims=" %%A in ("%inputFile%") do (
for %%F in ("%%A\.") do echo folder: %%~nxF
)
The ~nx FOR variable modifiers directly give you the name and extension of the end of the path. Type HELP FOR from the command line to read about all the modifiers that are available to FOR variables.
For variable filenames:
#Echo OFF
:: By Elektro H#cker
set "File=File.ext"
Call :Get_paths "%InputFile%"
Pause&exit
:Get_paths
Set "AbsolutePath=%~dp1"
set "AbsolutePath=%AbsolutePath:\= %"
FOR %%# in (%AbsolutePath%) do (
Set "LastFolder=%%#"
Echo Folder: %%#
)
Echo Last Folder: %LastFolder%
GOTO:EOF
Output:
Folder: C:
Folder: Users
Folder: Administrador
Folder: Desktop
Last Folder: Desktop
For files:
#Echo OFF
:: By Elektro H#cker
set "File=test.txt"
For /F "Tokens=* usebackq" %%# in ("%FILE%") DO (
Set "AbsolutePath=%%~dp#"
Call set "AbsolutePath=%%AbsolutePath:\= %%"
CMD /Q /C "#FOR %%# in (%%AbsolutePath%%) do (Echo Folder: %%#)"
)
Pause&Exit
InputFile content must contains filename or folder.
ex)
D:\Test1 <= folder
D:\Test2\file.txt <= file
D:\Test3\01. folder <= folder but recognize file. that contain extension.
My code is:
SETLOCAL EnableDelayedExpansion
SET lastFolder=
SET InputFile=somar.txt
FOR /F %%F IN (%InputFile%) DO (
CALL :__GetFolderName "%%F"
#ECHO lastFolder: !lastFolder!
)
GOTO :EOF
:: ******************** Inner Batch
:__GetFolderName
IF "%~x1"=="" SET lastFolder=%~n1 & GOTO :EOF
SET dp=%~dp1
CALL :__GetFolderName "%dp:~0,-1%"
GOTO :EOF
:: ********************
ENDLOCAL
Result is:
lastFolder: Test1
lastFolder: Test2
lastFolder: Test3

Resources