returning var back to calling batch file - variables

i start a batch file to process some code, at a time it calls another batchfile and should get returned a variable, but the methods explained in man pages about local/endlocal seem not to work here, what am i doin wrong please?
first batch file:
#ECHO OFF
setlocal
call secondbatchfile.bat xyz
echo. [%val1%]
second batch file:
#if (#a==#b) #end /* <== btw what does this code do ???
#echo off
setlocal enabledelayedexpansion
set "URL=%~1"
set bla bla ...
do bla bla ...
for /f "delims=" %%I in ('cscript /nologo /e:jscript "%~f0" "%URL%"') do (
rem trim whitespace from beginning and end of line
for /f "tokens=*" %%x in ("%%~I") do set "line=%%x"
rem test that trimmed line matches "variable=number"
echo !line! | findstr /i "^to[a-z]*=[0-9]*" >NUL && (
rem test was successful. Scrape number.
for /f "tokens=2 delims==" %%x in ("%%I") do set "val1=%%x"
echo !val1! <== this works
ENDLOCAL & SET top=%val1% <== this not
)
)
this results in:
c:\test>firstbatchfile.bat
123456789 <== this works
[] <== this not
i tried different syntax of return var like !val1! or %%val1 - none worked. what am i missing?
UPDATE:
regarding to other example here on site i tried:
call seconbatchfile.bat xyz ret1
echo. [%2%] [%ret1%]
and in secon file changed:
rem ENDLOCAL & SET %2=!val1!
does not work either?
SOLUTION:
second batch file can be origin script from rojo reading out the whole website, i did leave the trim and match syntax lines to only return relevant matches:
for /f "delims=" %%I in ('cscript /nologo /e:jscript "%~f0" "%URL%"') do (
rem trim whitespace from beginning and end of line
for /f "tokens=*" %%x in ("%%~I") do set "line=%%x"
rem test that trimmed line matches "variable=number"
echo !line! | findstr /i "^[a-z]*=[0-9]*" >NUL && (
echo(%%I
)
)
and the first batch file calling it will do the search for two needed parameters like this:
#ECHO OFF
setlocal
for /f "delims=" %%I in ('secondbatchfile.bat "http://xyz"') do (
echo %%I | findstr /i "top" >NUL && (
for /f "tokens=2 delims==" %%x in ("%%I") do (
set "updir=%%x"
)
)
echo %%I | findstr /i "low" >NUL && (
for /f "tokens=2 delims==" %%x in ("%%I") do (
set "lowdir=%%x"
)
)
)
echo.[%updir%]
echo.[%lowdir%]
many thanks to rojo for fantastic code

The easiest solution is to have your second batch file echo its result, and capture it using a for loop in the first batch file. Cancelling your setlocal to pass an environment variable back to the calling script is a messy affair.
first.bat:
#echo off
setlocal
for %%x in (
"http://10.0.0.1/foo/vars.txt"
"http://10.0.0.1/bar/vars.txt"
"http://10.0.0.1/baz/vars.txt"
"http://10.0.0.1/qux/vars.txt"
"http://10.0.0.1/corge/vars.txt"
) do (
for /f "delims=" %%I in ('fetchvalue.bat "%%~x"') do (
set "val1=%%I"
)
echo.[%val1%]
)
fetchvalue.bat:
#if (#a==#b) #end /*
:: fetchvalue.bat <url>
:: output the "value" part of variable=value from a text file served by http
#echo off
setlocal
if "%~1"=="" goto usage
echo "%~1" | findstr /i "https*://" >NUL || goto usage
set "URL=%~1"
for /f "delims=" %%I in ('cscript /nologo /e:jscript "%~f0" "%URL%"') do (
rem trim whitespace from beginning and end of line
for /f "tokens=*" %%x in ("%%~I") do set "line=%%x"
rem test that trimmed line matches "variable=number"
echo !line! | findstr /i "^to[a-z]*=[0-9]*" >NUL && (
rem test was successful. Scrape number.
for /f "tokens=2 delims==" %%x in ("%%I") do echo(%%x
)
)
goto :EOF
:usage
echo Usage: %~nx0 URL
echo for example: %~nx0 http://www.google.com/
echo;
echo The URL must be fully qualified, including the http:// or https://
goto :EOF
JScript */
var x=new ActiveXObject("Microsoft.XMLHTTP");
x.open("GET",WSH.Arguments(0),true);
x.setRequestHeader('User-Agent','XMLHTTP/1.0');
x.send('');
while (x.readyState!=4) {WSH.Sleep(50)};
WSH.Echo(x.responseText);
Here's an example first.bat that will sort the fetched values, set low to the lowest value, and set high to the highest.
#echo off
setlocal enabledelayedexpansion
for %%x in (
"http://10.0.0.1/foo/vars.txt"
"http://10.0.0.1/bar/vars.txt"
"http://10.0.0.1/baz/vars.txt"
"http://10.0.0.1/qux/vars.txt"
"http://10.0.0.1/corge/vars.txt"
) do (
set low=
for /f "delims=" %%I in ('fetchvalue.bat "%%~x" ^| sort') do (
if not defined low set "low=%%I"
set "high=%%I"
)
echo low: !low!
echo high: !high!
)

Your inner batch file is ending by setting an environment variable named top: set top=%val1%. You'll need to change that to set val1=%val1%.
...
echo !val1!
ENDLOCAL & SET val1=%val1%

Related

Extract line below Findstr criteria in Batch file for cycle

I'm trying to extract from a set of txt files the line
placed 2 rows below the one matching search criteria
and redirect output to a csv file.
I managed to do that for a specific txt file in the set,
but I'm getting troubles in writing the For Cycle
to batch-scan each txt in a given folder.
Through this, I wrote the following code to scan
a specific file. It works fine:
setlocal EnableDelayedExpansion
cd "myFolder"
if exist myOutput.csv del myOutput.csv
for /F "delims=:" %%A in ('findstr /B /N /C:"myCriteria" "myFile.txt"') do (
set /A LineBelow=%%A+2
set "LineBelow=!LineBelow!: "
)
(for /F "tokens=1* delims=:" %%A in ('findstr /N "^" "myFile.txt" ^| findstr /B "%LineBelow%"') do ^
echo %%B>>myOutput.csv)
start myOutput.csv
ENDLOCAL
When I tried to generalize the code in a For Cycle to scan each txt in myFolder
I got an error in Findstr: !LineBelow! happens to be an empty variable...
Here's the flawed For Cycle:
setlocal EnableDelayedExpansion
cd "myFolder"
if exist myOutput.csv del myOutput.csv
for %%F IN ("*.txt") do (
(
for /F "delims=:" %%A in ('findstr /B /N /C:"myCriteria" "%%F"') do (
set /A LineBelow=%%A+2
set "LineBelow=!LineBelow!: "
))
(for /F "tokens=1* delims=:" %%A in ('findstr /N "^" "%%F" ^| findstr /B "!LineBelow!"') do ^
echo %%B>>myOutput.csv))
start myOutput.csv
ENDLOCAL
Could anybody help me in correcting this code?
Thanks
#echo off
setlocal enableextensions enabledelayedexpansion
cd "myFolder"
> myOutput.csv (
for /f "tokens=1,2 delims=:" %%a in ('
findstr /b /n /c:"myCriteria" *.txt
') do (
set /a "line=%%b+2"
for /f "tokens=1,* delims=:" %%c in ('
findstr /n "^" "%%a" ^| findstr /b /c:"!line!:" 2^>nul
') do echo(%%d
)
)
This uses findstr to directly enumerate all the lines matching the myCriteria and include in the output the name of the file (%%a) and the number of the line (%%b). This information is used to retrieve the final line (%%d) from the matching files.

Batch for loop using wmic

The output of the below
wmic logicaldisk get providername /value
using cmd (with limited user rights) on the computer I'm using is:
ProviderName=
ProviderName=
ProviderName=\\xxx-SN-NA01\Users2\N\ni
ProviderName=\\xxx-sn-na01\Software_Ca
ProviderName=\\xxx-sn-na01\TSO
I'm tring to get to the following stored in a variable named %drives_paths_wmic%:
\\xxx-SN-NA01\Users2\N\ni \\xxx-sn-na01\Software_Ca \\xxx-sn-na01\TSO
Then for the content of this to be transferred into the variable %file%.
The batch code I currently have is:
#echo off
setlocal enabledelayedexpansion
for /F "tokens=2 delims='='" %%A in ('wmic logicaldisk get providername /value') do (
echo %%A >> %drive_paths_Wmic%
)
echo %drive_paths_Wmic%
echo %drive_paths_Wmic% >> %file%
Edit: the problem is that nothing gets stored in the %drive_paths_Wmic% variable.
Since the batch file would need to be run on Windows 7 and XP computers, I can't use PowerShell.
Please advise changes to the batch code in order to do this?
You do not specify a problem. However:
'1'. delims== syntax
for /F "tokens=2 delims==" %%A in ('wmic logicaldisk get providername /value') do #echo %%A
Is the output from above command right? I dare say not, because
'2'. all output from wmic is Unicode. To convert to ASCII try next code snippet:
wmic logicaldisk get providername /value >somename.txt
for /F "tokens=2 delims==" %%A in ('type somename.txt') do #echo %%A
'3'. Result to variable:
set "file="
rem variable initialized now
rem ... some code ...
for /F "tokens=2 delims==" %%A in ('type somename.txt') do set file=!file! %%A
rem ... some code ...
echo !file!
echo %file%
or may be set "file=!file! %%A" as well
Complete batch:
#ECHO OFF >NUL
#SETLOCAL enableextensions enabledelayedexpansion
set "drive_paths_Wmic="
rem variable initialized now
rem ... some code ...
wmic logicaldisk get providername /value >somename.txt
for /F "tokens=2 delims==" %%A in ('type somename.txt') do (
set drive_paths_Wmic=!drive_paths_Wmic! %%A
#rem ... some code ...
)
echo !drive_paths_Wmic!
echo %drive_paths_Wmic%
Endlocal
goto :eof
Output (on my computer):
C:\bat>fivmic
\\pc1870a\ttemp \\PC1870A\Install
\\pc1870a\ttemp \\PC1870A\Install
Output (part with echo ON)
C:\bat>fivmic
C:\bat>wmic logicaldisk get providername /value 1>somename.txt
C:\bat>for /F "tokens=2 delims==" %A in ('type somename.txt') do set drive_paths_Wmic=!drive_paths_Wmic! %A
C:\bat>set drive_paths_Wmic=!drive_paths_Wmic! \\pc1870a\ttemp
C:\bat>set drive_paths_Wmic=!drive_paths_Wmic! \\PC1870A\Install
C:\bat>rem ... some code ...
C:\bat>echo !drive_paths_Wmic!
\\pc1870a\ttemp \\PC1870A\Install
C:\bat>echo \\pc1870a\ttemp \\PC1870A\Install
\\pc1870a\ttemp \\PC1870A\Install
And if %file% variable contains valid filename, then you could redirect echo to that file, e.g. echo bubu >> anyname.txt appends text bubu (on a new line) to file anyname.txt. In your script:
set file="anyname.txt"
echo %drive_paths_Wmic% >> %file%

1 Character in path changing... How to Handle?

I have a path:
\%VARIABLE%svr0001\e$\Users\%VARIABLE%POS00??\E2ELOGS*.dbg
The ONLY characters that changes is the '??' (%VARIABLE%POS00??).
Values could be from 01 through 15 (01,02,03,04,05,06,07,08,09,10,11,12,13,14,15)
How would I make the following script work without creating if path exist statements for every potential changing value:
setlocal enabledelayedexpansion
for /f "delims=" %%a in ('find /c /i "Error : -2" "\\%VARIABLE%svr0001\e$\Users\%VARIABLE%POS00??\E2ELOGS\*.dbg"') do (
set "$line=%%a"
set "$lastchar=!$line:~-1!"
if !$lastchar! gtr 0 echo %%a >>NO_ACK_ERROR-2.txt
)
Try like this :
#echo off
setlocal enabledelayedexpansion
for /l %%x in (1,1,15) do (
set "$number=0%%x"
for /f "delims=" %%a in ('find /c /i "Error : -2" "\\%VARIABLE%svr0001\e$\Users\%VARIABLE%POS00!$number:~-2!\E2ELOGS\*.dbg"') do (
set "$line=%%a"
set "$lastchar=!$line:~-1!"
if !$lastchar! gtr 0 echo %%a >>NO_ACK_ERROR-2.txt
))
If I understood it correct, you want to check the log files with the name POS001-POS0015, below may be the answer for you.
setlocal enabledelayedexpansion
for /l %%i in (1,1,15) do (
set "num=%%i"
if "!num:~0,1!" neq "0" set "num=0!num!"
set "filepath=\\%VARIABLE%svr0001\e$\Users\%VARIABLE%POS00!num!\E2ELOGS\*.dbg"
for /f "delims=" %%a in ('find /c /i "Error : -2" "!filepath!"') do (
set "$line=%%a"
set "$lastchar=!$line:~-1!"
if !$lastchar! gtr 0 echo %%a >>NO_ACK_ERROR-2.txt
)
Cheers, G

Skipping variable looks impossible

So I want to Echo %%a into another txt file, but seems nothing works to me.
Here's the code :
for /f "delims=" %%a in (
'dir "*.txt" /b /s /a-d'
) do Echo for /f "delims=" %%a in ^( >> "%%a"
Simple : output file looks like:
"for /f "delims=" C:\Documents and
Settings\xxxxx\Desktop\alpha\lol.txt in ( " .
I just need not a full path but "%%a". Bat file.
You want the literal %%a ?
Try %%%%a
Second suggestion:
Try %%%%^a
Third - change the metavariable (loop-control variable) to %%b
for /f "delims=" %%b in (
'dir "*.txt" /b /s /a-d'
) do Echo for /f "delims=" %%%%a in ^( >> "%%b"
Try this:
for /f "delims=" %%a in ('dir "*.txt" /b /s /a-d' ) do Echo %%a >> output.txt
As you saw, it's not directly possible to escape the %%a expression in a loop.
But like Magoo mention, it can be solved with changing the loop parameter.
You could also use the parser to create the %%a output.
setlocal EnableDelayedExpansion
set "static=for /f "delims=" %%%%a in ("
for /f "delims=" %%a in ( 'dir "*.txt" /b /s /a-d') do (
echo !static! >> "%%a"
)
The content of the variable static will be expanded, but the inner %%a will not expanded later.

Batch: for /f +xcopy output - Save to .log

I have the next script, and I need it to save all the xcopy files copy outputs to one log file,
:tmdeploy
title Deploying Edithor - %deployer%
set src_folder=S:\ApliTelinver\Compilacion\Edithor 10.5\CompilacionQA
set dst_folder=S:\ApliTelinver\Ambientes-Edithor\Sincronizacion\Test\Test-Mantenimiento
set filelist=filelist-tm.txt
echo Origen: %src_folder%
echo Destino: %dst_folder%
echo.
REM for /f %%i in (%filelist%) DO xcopy /S/E/U/Y "%src_folder%\%%i" "%dst_folder%" > "%dd%.log"
for /f "delims=" %%i in (%filelist%) do (
xcopy /S/E/U/Y "%src_folder%\%%i" "%dst_folder%" > "%dd%.log"
)
echo.
pause
goto end
The problem is that I only get the last file copy in the output. And how to properly do a timestamp for .log file?
Thank you
You should use the appended redirection operator, >> instead of >.
So, your for loop will look like this:
REM for /f %%i in (%filelist%) DO xcopy /S/E/U/Y "%src_folder%\%%i" "%dst_folder%" >> "%dd%.log"
for /f "delims=" %%i in (%filelist%) do (
xcopy /S/E/U/Y "%src_folder%\%%i" "%dst_folder%" >> "%dd%.log"
)