Executing commands one with a loop with cmd

跟風遠走 提交于 2020-06-29 03:45:50

问题


I want to create a batch file that both executes a command once, and do a loop at the same time. When the loop occurs again, the command won't be executed anymore. Here is the code for the loop:

@echo off
setlocal EnableDelayedExpansion
for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"

FOR /L %%n in (1,1,10) DO (
    call :spinner
    ping localhost -n 2 > nul
)
exit /b

:spinner
set /a "spinner=(spinner + 1) %% 4"
set "spinChars=\|/-"
<nul set /p ".=Rebuilding, please wait... !spinChars:~%spinner%,1!!CR!"
exit /b

However there's a problem: The loop will execute and only executes when the command is done. And there are no timeouts for the loop, so basically, it will do the loop forever, until I press Ctrl + C. Can anyone help me with this? And if you can, please make the code above better. Thanks in advance.


回答1:


Set a variable with a true value when the command is executed in the first instance, and Conditional testing in that variable prior to executing said command

If not "!EXC!" == "" (Echo First Run) Else (Set "EXC=True")

Example uses delayed expansion as it is usable both in For Loops and Label Loops.

If you want to Break the Loop, Use the conditional testing to Goto :Label

Update

Now that you've provided more detail in your question, I believe something like this is what you're going for.

@echo off
setlocal EnableDelayedExpansion
for /f %%a in ('copy /Z "%~dpf0" ^> nul') do set "CR=%%a"
set "spinChars=\|/-"
   for /f "delims=#" %%a in ('"prompt #$H# &echo on &for %%b in (1) do rem"') do (
      set "BS=%%a"
      set "BS=!BS:~0,1!"
   )

<nul set/p=Rebuilding, please wait... 
FOR /L %%. in () DO (
REM insert conditional testing to break loop Here
    set /a "spinner=(spinner + 1) %% 4"
    For %%/ in (!Spinner!) Do <nul set /p=%BS%!spinChars:~%%/,1!
)
exit /b

:End_Loop
Echo You have Exited the process
Pause
Exit /B

The Definition of the Backspace Character comes from this post

Whatever process your waiting for in the loading loop you will need some method to test for it's completion. Seeing as you've not detailed, I'll suggest some options:

  • Existance of a file
  • Value of a Variable
  • result of testing against tasklist to see if a task is still active.

If you provide more detail regarding the command / process you are waiting on, a better answer regarding the conditional testing can be offered.

An example method that runs a subroutine as a seperate instance in the same window, and uses Signal Files to communicate to the main Loop when command execution has completed:

::: ** Batch Multithreading example by T3RRY ** :::
    @Echo Off & CD "%~dp0"                      :::
:::::::::::::::::::::::::::::::::::::::::::::::::::

::: - Define any Variables to be used by both Environments
    Set "spinChars=\|/-"
::: - Test if Thread Two is to be executed
    If /I "%~1" == "Thread2" Goto :Thread2
::: - Localise Thread Ones Environment
    Setlocal EnableDelayedExpansion
::: - Ensure previous Signal files removed in case program exited incorrectly
    Del /Q /F "%TEMP%\CMDrun.log"
    Del /Q /F "%TEMP%\CMDend.log"
    CLS
::: - Define Backspace Character for Animation
    For /F "delims=#" %%a in ('"prompt #$H# &echo on &for %%b in (1) do rem"') do (
      Set "BS=%%a"
      Set "BS=!BS:~0,1!"
    )

    <Nul Set/P=Processing, please wait. 
:Loop
::: - Launch Thread Two in Same window if Not already Running
::: - Conditional tests on signal files redirect errors to Standard error to prevent erroneous output
::: - when testing occurs at the same time the file is being written to.
    (IF Not Exist "%TEMP%\CMDrun.log" Start /B "" "%~F0" Thread2) 2>Nul
::: - Animation To indicate commands in thread one are running. A Loop is used in this example.
    Set /A "spinner=(spinner + 1) %% 4"
    For %%S in (!Spinner!) Do <Nul Set /P=%BS%!spinChars:~%%S,1!
::: - Exit Thread One once Thread Two has Completed
    (IF Exist "%TEMP%\CMDend.log" Goto :End_Loop) 2>Nul
Goto :Loop

:End_Loop
::: - Clean up Signal Files
    Echo.
    Del /Q /F "%TEMP%\CMDrun.log"
    Del /Q /F "%TEMP%\CMDend.log"
    Echo Process Complete
    Pause
::: - Demonstrate stability of multithreading through repetition
    Start "" "%~F0"
Exit

:Thread2
::: Localise Thread Two's Environment
    Setlocal EnableDelayedExpansion
    >"%TEMP%\CMDrun.log" (Echo running)
::: - Title update to demonstrate commands executed in thread two are running
    For /L %%# In (1,1,10000) Do (
        Set /a "spinner=(spinner + 1) %% 4"
        For %%S in (!Spinner!) Do TITLE !spinChars:~%%S,1! Output %%#
    )
    >"%TEMP%\CMDend.log" (Echo finished)
::: - Hard exit of Thread Two used to prevent script overflow.
EXIT


来源:https://stackoverflow.com/questions/61696996/executing-commands-one-with-a-loop-with-cmd

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!