Everything before the for loop works fine, i can add "pause" to it and it pauses, but inside the for loop it does not work. I have tried to add pause but it doesn't, and the pause after the loop does not occur.
#echo off
setlocal enabledelayedexpansion
setlocal
for %%g in ( * ) do (
pause
echo %%g
set strEnd=___EndOfString___
set strFilename=%%g
set strFile=!strFilename!!strEnd!
echo !strFile!
pause
:loop
set strChar=!strFile:~0,1!
set strFile=!strFile:~1!
if !strChar!==a echo A
pause
if not !strFile!==!strEnd! goto loop
)
pause
endlocal
This construct should work. You can adjust timeouts duration.
#echo off
setlocal enabledelayedexpansion
for %%g in ( * ) do (echo %%g
set strEnd=___EndOfString___
set strFilename=%%g
set strFile=!strFilename!!strEnd!
echo !strFile!
timeout 2 >nul
call :loop
)
pause
exit /b
:loop
:: add more code here
timeout 2 >nul
exit /b
However, your original script inside the :loop is not correct, and needs to be changed depending on the batch purpose.
Related
Ive been trying to loop a batch file exactly 5 times using the set /a operation and so far no luck! Could someone help me?
#ECHO OFF
set loopCount=0
:loop
echo Checked %loopCount% times...
set /a loopCount=1+%loopCount%
if loopCount == 5 (goto exit) else (goto loop)
:exit
cls
echo Finished after %loopCount% times
pause >nul
Best of luck to whoever can help me
Here's a couple of examples to help you.
Using GoTo with a label:
#Set "loopCount=0"
:loop
#Set /A loopCount += 1
#Rem Some actual command goes here.
#Echo Checked %loopCount% times...
#If %loopCount% Lss 5 GoTo loop
#%SystemRoot%\System32\timeout.exe /T 2 /NoBreak 1>NUL
#ClS
#Echo Finished after being checked %loopCount% times.
#Pause 1>NUL
Alternatively, using a For /L looping mechanism:
#Set "maxCount=5"
#For /L %%G In (1,1,%maxCount%) Do #(
Rem Some actual command goes here.
Echo Checked %%G times...
)
#%SystemRoot%\System32\timeout.exe /T 2 /NoBreak 1>NUL
#ClS
#Echo Finished after being checked %maxCount% times.
#Pause 1>NUL
If you need to execute the entire batch script 5 times, the following method of storing an execution count in an alternate data stream of the script can be used:
#Echo off
more < "%~f0:Count" 2>&1 > nul && (
For /f "usebackq delims=" %%G in (`more ^< "%~f0:Count"`)Do Set /A Count=%%G+1
) || (
Set /A "Count+=1"
)
Echo(%Count% >"%~f0:Count"
:# Your script below
Echo(Script execution: %Count%
:# Terminate script execution after count reached
If %Count% EQU 5 (
Echo(0 >"%~f0:Count"
Exit /B
)
"%~f0"
So I am trying to create a file that will read a text file called saves. In saves I want it to check up to 5 time for 1:, 2:, 3: ,4:, and 5:. The issue is that when I run this for loop to check the file 5 times it always outputs the same thing and no matter what will say there are no saves. Any help or advice is much appreciated.
#ECHO off
SETLOCAL EnableDelayedExpansion
SET test=0
FOR /L %%i IN (1,1,5) DO (
FINDSTR %%i: Saves.txt >NUL && SET /a %test%+1
ECHO %test%
)
IF %test% EQU 0 ECHO There are no saves. & GOTO :end
IF %test% GTR 0 ECHO There are saves.
:END
PAUSE
You are not using the SET command correctly and you need to use delayed expansion to display the variable correctly when inside a parenthesized code block.
#ECHO off
SETLOCAL EnableDelayedExpansion
SET test=0
FOR /L %%i IN (1,1,5) DO (
FINDSTR /B %%i: Saves.txt >NUL && SET /a test+=1
ECHO !test!
)
IF %test% EQU 0 ECHO There are no saves. & GOTO :end
IF %test% GTR 0 ECHO There are saves.
:END
PAUSE
An easier option would be.
FINDSTR /B "1: 2: 3: 4: 5:" Saves.txt >NUL 2>&1 && (ECHO There are saves.) || (ECHO There are no saves.)
If all your lines begin with a number and colon then you can just do this.
FOR /F "tokens=1 delims=:" %%G IN (saves.txt) do set numsaves=%%G
I am facing issue with reading contents of CSV files in batch script. I have a series of files say My_A_File.csv, My_B_File.csv ... My_Z_File.csv. The issue I was facing is reading special characters in them. Hence, wanted to read the values with delayedexpansion turned off.
When I read the values in the block with disabledelayedexpansion, they are empty! How can I handle this?
Script:
#echo off
setlocal enabledelayedexpansion
for /L %%g in (65,1,90) do (
cmd /c exit /b %%g
set codeval=!=ExitCodeAscii!
set fileToReadFrom=My_!codeval!_File.csv
if exist My_!codeval!_File.csv (
echo Outer-!fileToReadFrom!
echo Outer-!codeval!
setlocal disabledelayedexpansion
echo Inner-%fileToReadFrom%
echo Inner-%codeval%
endlocal
)
)
Output:
Outer-My_A_File.csv
Outer-A
Inner-
Inner-
This how the delayed expansion is supposed to work.However you can access the variables with CALL but this will the performance (mind that you cant CALL FOR ):
#echo off
setlocal enabledelayedexpansion
for /L %%g in (65,1,90) do (
cmd /c exit /b %%g
set codeval=!=ExitCodeAscii!
set fileToReadFrom=My_!codeval!_File.csv
if exist My_!codeval!_File.csv (
echo Outer-!fileToReadFrom!
echo Outer-!codeval!
setlocal disabledelayedexpansion
call echo Inner-%%fileToReadFrom%%
call echo Inner-%%codeval%%
endlocal
)
)
or you can use pipes.Which also will hit the performance (now you can use
break|for "usebackq" %%a in ("Inner-%%fileToReadFrom%%") do #echo %%~a):
#echo off
setlocal enabledelayedexpansion
for /L %%g in (65,1,90) do (
cmd /c exit /b %%g
set codeval=!=ExitCodeAscii!
set fileToReadFrom=My_!codeval!_File.csv
if exist My_!codeval!_File.csv (
echo Outer-!fileToReadFrom!
echo Outer-!codeval!
setlocal disabledelayedexpansion
break|echo Inner-%%fileToReadFrom%%
break|echo Inner-%%codeval%%
endlocal
)
)
Use a subroutine to process code with delayed expansion disabled as follows:
#echo off
rem skip subroutine code
goto :toMain
:toProcessDDE
rem subroutine to process delayed expansion disabled
setlocal disabledelayedexpansion
echo Inner-%fileToReadFrom%
echo Inner-%codeval%
endlocal
exit /B
:toMain
setlocal enabledelayedexpansion
for /L %%g in (65,1,90) do (
cmd /c exit /b %%g
set codeval=!=ExitCodeAscii!
set fileToReadFrom=My_!codeval!_File.csv
if exist My_!codeval!_File.csv (
echo Outer-!fileToReadFrom!
echo Outer-!codeval!
call :toProcessDDE
)
)
Read
CALL: Call one batch program from another, or call a subroutine and
EXIT: … quit the current subroutine …
I'm making a batch script to stop several services , however i get the syntax is incorrect error at second FOR which loops in serviceList.TEMP
setlocal EnableDelayedExpansion
setlocal enableExtensions
::queryex output file
sc queryex>services.TEMP
find /i /N "DISPLAY_NAME: Hotspot" services.TEMP>tmp1.TEMP
FOR /F "skip=2" %%G in (tmp1.TEMP) do (
set num=%%G
set num=!num:~1,3!
echo !num!>serviceList.TEMP
)
FOR %%X in (serviceList.TEMP) do (
set /a "SKIP_LINES=%%G+7"
set secondForFilter="skip=%SKIP_LINES%"
FOR /F %secondForFilter% %%Z in (services.TEMP) do (
call debug.cmd REM debug.cmd -> echo debug pause>nul
set serv=%%Z
set "serv=!serv: =!" REM Extract PID
set "serv=!serv::=!" REM Extract PID
set procID=!serv!
taskkill /pid %procID% /f >>debug.txt 2>>debug.txt
goto secondLoopEnd
)
:secondLoopEnd
)
del /S *.TEMP >>debug.txt 2>>debug.txt
the problem is here:
FOR %%X in (serviceList.TEMP) do (
set /a "SKIP_LINES=%%G+7"
set secondForFilter="skip=%SKIP_LINES%"
FOR /F %secondForFilter% %%Z in (services.TEMP) do (
call debug.cmd REM debug.cmd -> echo debug pause>nul
the usual approach when you set value in brackets context is to use delayed expansion but it wont work for parametrized for options.
Here you'll need a subroutine.
And you have GOTO in the for loop. GOTO breaks for context and the loops will be not called after goto is executed.
And rem cannot be used on the same line as the code without "&"
Consider something like this (though I cannot check the logic of the bat):
setlocal EnableDelayedExpansion
setlocal enableExtensions
::queryex output file
sc queryex>services.TEMP
find /i /N "DISPLAY_NAME: Hotspot" services.TEMP>tmp1.TEMP
FOR /F "skip=2" %%G in (tmp1.TEMP) do (
set num=%%G
set num=!num:~1,3!
echo !num!>serviceList.TEMP
)
FOR %%X in (serviceList.TEMP) do (
call :subroutine %%G
)
del /S *.TEMP >>debug.txt 2>>debug.txt
exit /b %errorlevel%
:subroutine
setlocal enableDelayedExpansion
set /a skiplines=%~1+7
set "filter="skip=%skiplines%""
FOR /F %filter% %%Z in (services.TEMP) do (
call debug.cmd
set serv=%%Z
rem extract PID
set "serv=!serv: =!"
set "serv=!serv::=!"
set procID=!serv!
taskkill /pid !procID! /f >>debug.txt 2>>debug.txt
goto :break_for
)
:break_for
endlocal
exit /b
Should the > in your echo to serviceList.TEMP be a >> so that you append to the file?
echo !num!>>serviceList.TEMP
In which case, you should also ensure that the file is deleted prior to the appending operations.
Also, I assume you missed the /F from your FOR loop, as you're trying to read the lines of the serviceList.TEMP file, yes?
FOR %%X in (serviceList.TEMP) do (
Should be...
FOR /F %%X in (serviceList.TEMP) do (
?
Also, you can append to the same file with both std out and err by doing this...
someprocesshere 1> out.log 2>&1
The following code runs a continuous loop, which increments the variable counter. When counter reaches 10, it should call the set_varibles routine, and then continue in the loop from the place set_variables was called. However, the goto does not work. What is wrong, and is there a better solution? Thanks
#echo off
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
:set_variables
SET t=ooo
:my_loop
set /a counter=0
for /L %%n in (1,0,10) do (
echo !counter!
set /a counter=counter+1
if !counter! equ 10 (
echo now TEN
goto set_variables
)
)
#echo on
ENDLOCAL
CALL a subroutine (:label)
The following code runs a continuous loop, which increments the
variable counter. When counter reaches 10, it should call the
set_varibles routine, and then continue in the loop from the place
set_variables was called.
Exactly as proposed: echo now TEN and call :set_variables every tenth pass the endless loop.
#echo off
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
call :set_variables
:my_loop
set /a counter=0
for /L %%n in (1,0,10) do (
echo !counter!
set /a counter=counter+1
set /a auxcounter=counter%%10
if !auxcounter! equ 0 (
echo now TEN
call :set_variables
)
)
#echo on
ENDLOCAL
#goto :eof
:set_variables
SET t=ooo
#goto :eof
Your main problem is not the goto command, but the for /l
While usually a goto command will cancel any block of code (code in parenthesis), for /l loops are a different beast. There are only two ways to leave a running for /l: an exit command (not exit /b unless the code is running in a command line context), or if the counter is greater than the end value.
Than means that the goto can not go out of the loop. It will cancel the execution of the code inside the do clause, but the loop will not be finished until the end value is reached, and your for loop
start step end
for /L %%n in ( 1, 0, 10 ) do ...
has a step value of 0 making it impossible to reach the end value.
The equivalent to your posted code could be
#echo off
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
:set_variables
SET t=ooo
:my_loop
for /L %%n in (0,1,9) do (
echo %%n
set /a counter=%%n+1
rem ....
)
echo now TEN
goto set_variables
Isn't this what you want:
#echo off
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
:set_variables
:my_loop
for /L %%n in (1,1,10) do (
echo %%n
if %%n equ 10 (
echo now TEN
SET t=ooo
)
)
goto my_loop
#echo on
ENDLOCAL
Using GOTO within parenthesis - including FOR and IF commands - will break their context.
Some things look odd in your script. Why have a continuous loop and then restart it when a counter reaches 10? Why not use "in (1,1,10)" like in Monacraft's answer?
Why does this tweaked version not do what you want?
#echo off
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
set /a outer_counter=0
:set_variables
echo start of set_variables
SET t=ooo
:my_loop
set /a counter=0
for /L %%n in (1,1,10) do (
echo !counter!
set /a counter=counter+1
set /a outer_counter=outer_counter+1
if !counter! equ 10 (
echo now TEN
)
)
if !outer_counter! geq 100 goto after_loop
goto set_variables
:after_loop
echo FINISHED
#echo on
ENDLOCAL
pause
I hate when additional specifications are placed in comments instead of the question description, but this comment appeared below Monacraft's answer:
I want to re-run the routine which is called periodically within the loop.
Everytime the counter reaches a certain value, the routine must be called
and the counter variable reset.
So I think that the solution to all OP's requests is this:
#echo off
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
call :set_variables
:my_loop
for /L %%n in (1,0,10) do (
echo !counter!
set /a counter=counter+1
if !counter! equ 10 (
echo now TEN
call :set_variables
)
)
No matter what is placed here, because a *continuous loop* NEVER ENDS!
#echo on
ENDLOCAL
:set_variables
SET t=ooo
set /a counter=0
exit /B