Loop until variable != "" - batch-file

I want to make a batch file that sends certain values to a output.txt. I have the following code:
for /F "delims=" %%a in ('adb logcat -v threadtime | grep -m 1 'VAC: App Name is:'') do set appName=%%a
echo App Name= %appName% > output.txt
The problem is that the grep statement doesn't immediately return a value--not until a user performs a certain action on the Android device. So I need to create a loop around the "for" statement. I'll make an attempt below, but I know it's wrong.
do
while
%appName% = ""
for /F "delims=" %%a in ('adb logcat -v threadtime | grep -m 1 'VAC: App Name is:'') do set appName=%%a
if "%appName% != "" leave
enddo
echo App Name= %appName% > output.txt

set "appName="
:loop
for /F "delims=" %%a in (
'adb logcat -v threadtime ^| grep -m 1 "VAC: App Name is:"'
) do set "appName=%%a"
if not defined appName goto loop
It just clears the variable and keep looping until it gets any value in it

Here you go (although MC ND's answers looks good too):
Please note pipe needs to be escaped by caret^, I added a 1 secs wait ping -n 1 -w 1000 1.1.1.1 >nul
:while_loop
for /F "usebackq delims=" %%a in (`adb logcat -v threadtime ^| grep -m 1 'VAC: App Name is:'`) do set appName=%%a
ping -n 1 -w 1000 1.1.1.1 >nul
if not "%appName% == "" goto exit_loop
goto while_loop
:exit_loop
echo App Name= %appName% > output.txt

Related

Batch - "for /F loop" inside "for /L loop"

I have following problem:
I want to create a batch file looping through an amount of ip addresses to stop a certain service on remote pc's.
Cause the stopping process takes some time I need to have a second loop to query the state of the service and waiting until the service reached the state STOPPED.
Set /p StartIP="Start IP (101): "
Set /p EndIP="End IP (199): "
for /L %%n IN (%StartIP%, 1, %EndeIP%) DO (
psservice -u username -p password \\192.168.8.&&n stop 'ServiceName'
:CHECK
echo 5 sek.
ping 127.0.0.1 -n 5 > nul
for /F "tokens=3 delims=: " %%H in ('psservice -u username -p password \\192.168.8.%%n query 'ServiceName' ^| findstr " STATE"') do (
if NOT %%H==STOPPED (
echo.
echo state: %%H
goto CHECK
)
echo.
echo state: %%H
)
psservice -u username -p password \\192.168.8.%%n start 'ServiceName'
)
Now the point I stuck to:
My range of numbers '%%n' from the /L loop is getting destroyed after passing the /F loop the first time.
With an example it looks like this:
Set /p StartIP="Start IP (101): 101"
Set /p EndIP="End IP (199): 105"
for /L %%n IN (101, 1, 105) DO (
psservice -u username -p password \\192.168.8.101 stop 'ServiceName'
:CHECK
echo 5 sek.
ping 127.0.0.1 -n 5 > nul
for /F "tokens=3 delims=: " %%H in ('psservice -u username -p password \\192.168.8.101 query 'ServiceName' ^| findstr " STATE"') do (
if NOT %%H==STOPPED (
echo.
echo state: %%H
goto CHECK
)
echo.
echo state: %%H
)
psservice -u username -p password \\192.168.8.%%n start 'ServiceName'
)
In this example I have the ip range 192.168.8.101 to 192.168.8.105.
The batch is running well until the /F loop is run trough the first time.
After this moment the %%n parameter from my /L loop is gone. The service can't start again, cause the %%n parameter already missing and my /L loop can't continue too -.-
Someone an idea what I can do to solve this problem?
Thank you already for reading this post.
As MC ND said in his comment, issuing a GOTO within a FOR loop will break the loop. Actually, the issue is more general than that - issuing a GOTO within any block of code (paranthesized, or concatenated via &) will terminate the remainder of the block.
The simple solution is to extract the code that needs GOTO and put it in its own subroutine, and then CALL the routine from within your loop.
Set /p StartIP="Start IP (101):"
Set /p EndIP="End IP (199):"
for /L %%n IN (%StartIP%, 1, %EndIP%) DO (
psservice -u username -p password \\192.168.8.%%n stop 'ServiceName'
call :check %%n
psservice -u username -p password \\192.168.8.%%n start 'ServiceName'
)
exit /b
:CHECK
echo 5 sek.
ping 127.0.0.1 -n 5 > nul
for /F "tokens=3 delims=: " %%H in (
'psservice -u username -p password \\192.168.8.%1 query 'ServiceName' ^| findstr " STATE"'
) do (
echo.
echo state: %%H
if not %%H==STOPPED goto CHECK
)
exit /b

Batch Script ErrorLevel Output

I need help - I am trying to output any ErrorLevel that is 1 or greater into a log file. When I issue the command the log file never get's generated. Any help would be greatly appreciated.
Script:
for /f "delims=" %%i in (C:\_\Restart\Computer.txt) do (
start "%%i" \_\PStools\psexec \\%%i -u Administrator -p Password -i c:\restart.cmd
if not %errorlevel%==0 echo %errorlevel% > error.log
)
This script allows me to use PSEXEC and issue a restart command to all the computer at once. However several of them fail and I'd like to know which ones fail.
Thanks!
Is this the format I should use?
setlocal EnableDelayedExpansion
for /f "delims=" %%i in (C:\_\Restart\Computer.txt) do (
start "%%i" \_\PStools\psexec \\%%i -u Administrator -p Password -i c:\restart.cmd
if errorlevel 1 echo !errorlevel! > error.log
)
Script V3:
setlocal EnableDelayedExpansion
for /f "delims=" %%i in (C:\temp\list.txt) do (
start "" "shutdown" /m \\%%i -r -f -t 900
echo !errorlevel! && echo %%i
if errorlevel 1 echo !errorlevel! >> c:\temp\log.txt && echo %%i >> c:\temp\log.txt
)
-m = use remote computer
-r = reboot
-f = Force reboot
-t = delay of time before rebooting
you can use shutdown -? for more help on argument that can be passed to the reboot command.
Script v4 without the start command:
setlocal EnableDelayedExpansion
for /f "delims=" %%i in (C:\temp\list.txt) do (
shutdown /m \\%%i -r -f -t 900
echo !errorlevel! && echo %%i
if errorlevel 1 echo !errorlevel! >> c:\temp\log.txt && echo %%i >> c:\temp\log.txt
)

parallel processing in bat file for loop

I want a batch file to do parallel processing. I have a storedprocedure which returns 1000+ records(has unique rowid column along with other info). Iterating though each row works fine. However, it takes long time to complete 1000 loops. Is there a way to run two loops parallel without overlapping or having to maintain separate batch files. Can this be accomplished by having one .bat file.
WORKING CODE:
#echo off
setlocal EnableExtensions
set ListFile=%TEMP%\StudentList.tmp
Set varServerPath=http://xyz/ReportServer
sqlcmd -Q "exec dbo.Storedproc_StudentList" -S ServerName -d DatabaseName >"%ListFile%" 2>nul
if exist "%ListFile%" (
for /F "usebackq tokens=1,2,3,4 skip=2 delims=', " %%A in ("%ListFile%") do (
echo Processing StudentID %%A and SubjectID %%B ...
if not exist "%%D" mkdir "%%D"
rs -i C:\ReportRender\Student.rss -s%varServerPath% -e Exec2005 -v StudentID="%%A" -v SubjectID="%%B" -v vOutputFilePath="%%C" -v vReportPath="/Student Reports/ReportName.rdl" -l 900
)
del "%ListFile%"
)
exit
I tried doing something like having two for loops one from 1 to 200 and other from 201 to 400 and so on....but seems like i'm on the wrong track. It doesn't work, Please suggest.
#echo off
setlocal EnableExtensions
set ListFile=%TEMP%\StudentList.tmp
Set varServerPath=http://xyz/ReportServer
sqlcmd -Q "exec dbo.Storedproc_StudentList" -S ServerName -d DatabaseName >"%ListFile%" 2>nul
if exist "%ListFile%" (
for /F "usebackq tokens=1,2,3,4 skip=2 delims=', " %%A in ("%ListFile%") do (
for /L %%A in(1,1,200) do (
echo Processing StudentID %%A and SubjectID %%B ...
if not exist "%%D" mkdir "%%D"
rs -i C:\ReportRender\Student.rss -s%varServerPath% -e Exec2005 -v StudentID="%%A" -v SubjectID="%%B" -v vOutputFilePath="%%C" -v vReportPath="/Student Reports/ReportName.rdl" -l 900
)
for /L %%A in(201,1,400) do (
echo Processing StudentID %%A and SubjectID %%B ...
if not exist "%%D" mkdir "%%D"
rs -i C:\ReportRender\Student.rss -s%varServerPath% -e Exec2005 -v StudentID="%%A" -v SubjectID="%%B" -v vOutputFilePath="%%C" -v vReportPath="/Student Reports/ReportName.rdl" -l 900
)
)
del "%ListFile%"
)
exit
Thanks,
Your approach is wrong. You are executing a for /L %%A in (1,1,200) ... and a for /L %%A in (201,1,400) ... for each record in the %ListFile%. You need to distribute the records in the %ListFile% into the two parallel processes. Although this can be done in groups of 200 records, it is much simpler to do that one-by-one. Also, the only way to have parallel processes in a Batch file is via start command or using a | pipe. In this case you want to distribute several input records that will be read (and processed) by two "output processes", so the pipe approach is simpler.
#echo off
setlocal EnableDelayedExpansion
if "%1" neq "" goto %1
set ListFile=%TEMP%\StudentList.tmp
Set varServerPath=http://xyz/ReportServer
sqlcmd -Q "exec dbo.Storedproc_StudentList" -S ServerName -d DatabaseName >"%ListFile%" 2>nul
if not exist "%ListFile%" exit
set numProcs=2
( "%~F0" Input | "%~F0" Output ) 2>&1 | "%~F0" Output
del "%ListFile%"
exit
:Input
set i=0
for /F "usebackq tokens=1,2,3,4 skip=2 delims=', " %%A in ("%ListFile%") do (
set /A i+=1, proc=i%%numProcs
if !proc! equ 1 (
echo %%A %%B %%C %%D
) else (
>&2 echo %%A %%B %%C %%D
)
)
exit /B
:Output
for /F "tokens=1-4" %%A in ('findstr "^"') do (
echo Processing StudentID %%A and SubjectID %%B ...
if not exist "%%D" mkdir "%%D"
rs -i C:\ReportRender\Student.rss -s%varServerPath% -e Exec2005 -v StudentID="%%A" -v SubjectID="%%B" -v vOutputFilePath="%%C" -v vReportPath="/Student Reports/ReportName.rdl" -l 900
)
exit /B
The :Input part just distribute the "%ListFile%" records to Stdout (channel 1) and Stderr (channel 2), one by one.
The :Output part just take the %%A %%B %%C %%D values sent by :Input part and process they in the usual way; the input data is read from Stdin via findstr command.
The :Input and :Output parts could be in separate Batch files, but they are included in the same file and selected via a parameter and the if "%1" neq "" goto %1 command placed at beginning.
The most interesting code is the pipeline that run the 3 processes in parallel. The :Input part run and its Stdout output is feed into the first :Output process. The Stderr output (channel 2) of :Input part is redirected into Stdin via the 2>&1, so this output is feed into the second :Output process.
This method may also be used for more than two output parallel processes; you just need to add more similar parts changing the number 2 for 3, etc. For example, with three output processes the pipeline should be this one:
( ( "%~F0" Input | "%~F0" Output ) 2>&1 | "%~F0" Output ) 3>&1 | "%~F0" Output
However, it is very important that you note that this method does NOT necessarily imply that the whole process will run faster! This point depends on several factors, like the number of CPU cores and the speed/buffers of the disk drive. Just a test can answer this question...
Post the result, please.

How to verify root from adb shell?

In my script I have the following code:
for /f "delims=" %%a in ('adb -s devicename shell su') do #set res=%%a
echo %res%
But I get no output. How to properly check for su availability from a batch script?
set uid=
for /f "delims=" %%a in ('adb -s devicename shell "su 0 id -u 2>/dev/null"') do set uid=%%a
echo %uid%
%uid% will be 0 if su is available

batch file - getting ip from ping command

i have this command.
ping -n 1 piratelufi.com | find /i "reply from"
i want to get the ip inside the ping response. i thought of using %var:~0,10% but i have no idea how to redirect the output to echo.
i even tried to use pipe
ping -n 1 piratelufi.com | find /i "reply from" | echo %1
but the %1 variable does not represent the output of the first two commands. i even tried to use &1 but i failed. What is the 'variable' needed to echo out the output from the first two commands?
Check out the FOR command it's really cool:
FOR /f "tokens=1,3 delims=: " %%A IN ('ping -n 1 piratelufi.com') DO IF %%A==Reply ECHO IP IS %%B
Try the following:
for /f "tokens=2 delims=[]" %f in ('ping -4 -n 1 piratelufi.com ^|find /i "pinging"') do echo IP=%f

Resources