I'm creating a simple bat file that plays some ASCII animation stored in 120 .txt files. My script works but it works too fast. I'd like to find a way to slow it dow a bit. I've tried the TIMEOUT 1 command but it only plays 1 picture per second which is too slow. Is there a workable solution without moving from Windows 7 command line?
This is my script so far
#echo off
MODE CON: COLS=91 LINES=41
cls
:3
setlocal enableextensions enabledelayedexpansion
FOR /R %%i in (*.txt) do (type "%%i"
)
goto :3
You could use a FOR /L loop to introduce a delay. Here is a script that introduces an approximate 100 msec delay. A simple test near the top computes how many iterations are required to approximate 100 msec. The number will vary between machines. Adjust the definition of msecDelay as required to get your desired result.
#echo off
setlocal
:: Compute the number of iterations required to get the desired delay
set msecDelay=100
set ticks=100000
set "start=%time%"
for /l %%N in (1 1 %ticks%) do rem
set "stop=%time%"
for /f "tokens=3,4 delims=:.," %%A in ("%start%") do set /a start=1%%A%%B-10000
for /f "tokens=3,4 delims=:.," %%A in ("%stop%") do set /a stop=1%%A%%B-10000
if %start% gtr %stop% set /a stop+=6000
set /a delay=msecDelay*ticks/(stop-start)/10
MODE CON: COLS=91 LINES=41
cls
:3
FOR /R %%i in (*.txt) do (
type "%%i"
for /l %%n in (1 1 %delay%) do rem
)
goto :3
I'm wondering if you will get better results by moving CLS within the loop, just before your TYPE statement.
This is a very simple way to slow between frames
Example:
#echo exiting script
ping localhost -n 2 > nul
cls
#echo exiting script .
ping localhost -n 2 > nul
cls
#echo exiting script ..
ping localhost -n 2 > nul
cls
#echo exiting script ...
ping localhost -n 2 > nul
cls
#echo exiting script ....
ping localhost -n 2 > nul
cls
#echo exiting script .....
ping localhost -n 5 > nul
cls
Not built in, but still command line: sleep.exe from Windows Resource Kit (available here: http://www.microsoft.com/en-us/download/details.aspx?id=17657)
Usage: sleep time-to-sleep-in-seconds
sleep [-m] time-to-sleep-in-milliseconds
sleep [-c] commited-memory ratio (1%-100%)
Related
I'm trying to make a script to shutdown my computer.
It asks for input wether the value will be in minutes or hours, in order to convert them to seconds for the shutdown command.
This is what my script looks like and it doesn't work.
#echo off
color 0a
:home
echo Hours (h) or minutes (m)?
set /p unit=
if "%unit%"=="h" (
echo For how long do you want to delay it?
set /p value=
set /a secs="value*=60*60"
) if "%unit%"=="m" (
echo For how long do you want to delay it?
set /p value=
set /a secs="value*=60"
) else (
goto:home
)
rem shutdown /s /f /t %secs%
echo %secs%
echo Closing in 3 seconds.
ping 127.0.0.1 -n 4 > nul
If anyone could lighten me up or come up with a better way to achieve it (which I'm sure exists), it'd be great.
I feel stupid now.
I totally forgot about else if.
Anyways, here's the finished working script. Also, input is now case-insensitive.
#echo off
echo ****************************
echo * *
echo * QUICK SHUTDOWN SCHEDULER *
echo * *
echo ****************************
echo.
echo Hours (H) or minutes (M)?
:home
set /p unit=
if /I "%unit%"=="h" (
echo For how many hours do you want to delay it?
set /p value=
set /a secs="value*=60*60"
) else if /I "%unit%"=="m" (
echo For how many minutes do you want to delay it?
set /p value=
set /a secs="value*=60"
) else (
echo Please only type H or M.
goto:home
)
shutdown /s /f /t %secs%
echo Closing in 3 seconds.
ping 127.0.0.1 -n 4 > nul
You may use choice command to get the input from user instead set /P; this way, you don't even need to check the provided input because it always be correct. For further details type: choice /?.
You may also use an array to show a messsage with the right units name without using an if to identify it; see this post for further details.
#echo off
setlocal EnableDelayedExpansion
rem Define the "units" array
set "units[1]=minutes"
set "units[60]=hours"
choice /N /C MH /M "Hours (H) or minutes (M)? "
set /A unit=(%errorlevel%-1)*59 + 1
set /p "value=For how many !units[%unit%]! do you want to delay it? "
set /a "secs=value* unit *60"
shutdown /s /f /t %secs%
echo Closing in 3 seconds.
ping 127.0.0.1 -n 4 > nul
Here is a bit of my batch Loading script
Echo Loading
Echo ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
Echo ºÛ º
Echo ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ
ping localhost -n 2 > nul
cls
Echo Loading
Echo ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
Echo ºÛÛ º
Echo ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ
ping localhost -n 2 > nul
cls
Echo Loading
Echo ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
Echo ºÛÛÛ º
Echo ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ
exit
Using the cls code to wipe the screen makes the screen look like a "Blink". Is there a better way to clear the screen for this batch file? TIA
Just far from perfect less glitching option: Instead of repaint the full screen, repaint only the loading line (but this has to be last painted line in the screen).
The basic idea is to ouput the line ending with a carriage return but without a line feed so the cursor is moved to the start of the line to write again over the same line.
#echo off
setlocal enableextensions enabledelayedexpansion
Rem Get a carriage return character
set "CR=" & for /f %%a in ('copy /Z "%~f0" nul') do if not defined CR set "CR=%%a"
rem The progress bar
set "fill=[##########]"
cls
echo(:: computers were created to give humans time to think while waiting ....
rem For each character in the fill
for /l %%a in (2 1 11) do (
rem Calculate the right part of the bar
set "spaces=!fill:~%%a!"
rem Output the left and right parts of the bar and carriage return
<nul set/p ".=:: Loading something big !fill:~0,%%a!!spaces:#= !!CR!"
rem Pause for a second
ping -n 2 "" > nul
)
echo(
echo(:: Done
If you can not change your code/design so the last line is the only one repainted, at least try to enclose the painting operation inside a block (code enclosed in parenthesis) so in each paint operation commands are only parsed once, and prepare everything before starting to paint. It will not avoid the glitches, but will be less evident
#echo off
setlocal enableextensions enabledelayedexpansion
for /l %%a in (0 10 100) do (
call :loadingScreen %%a
>nul ping -n 2 ""
)
echo(:: Done
goto :eof
:loadingScreen percent
setlocal enableextensions enabledelayedexpansion
rem Prepare everything
set "sb=+----------+"
set "fill=^|##########^|"
set "eb=+----------+"
set /a "chars=2+%~1/10"
set "spaces=!fill:~%chars%!"
set "loadBar=!fill:~0,%chars%!!spaces:#= !"
rem Time to paint
( cls
echo(:: computers were created to give humans time to think while waiting .... %time%
echo(
echo( %sb%
echo( Loading something big %loadBar%
echo( %eb%
echo(
)
goto :eof
I've tried to create an invisible countdown.
For example, the script starts the countdown, but in the meantime the script runs like an MMORPG. When you are entering an instance dungeon, it starts the countdown and you can walk etc. But when I do it with PING -n 6 127.0.0.1 //Delay the script for 5 seconds. I want the PING to run in the background and meanwhile the script goes on. I've got a response from Stephan but his code didn't work :(
Stephan's Code:
#echo off
setlocal enabledelayedexpansion
REM create a CarriageReturn:
for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"
for /L %%i in (5,-1,0) do (
<nul set /p =King Albireo is spawning in %%i seconds...!CR!
ping -n 2 127.0.01 >nul
)
goto Main
:Main
#title Example: Countdown
cls
echo It works
pause
Can someone make this script so it is running in the background and meanwhile the script goes on.
I know I used the same words over and over just to make sure everyone is getting what I am trying to say.
BTW thanks Stephan for the code.
You can try with
start "" /b cmd /q /v /e /c"(for /l %%a in (5 -1 1) do (echo respawn in %%a seconds&>nul ping -n 2 ""))&echo RESPAWN"
This is probably impossible, but I have a loop that displays a animated logo by using TYPE to type logo_(framenumber).txt and the framenumber is determined by a loop:
:s
if %m%==379 set m=0
cls
TYPE Logo_%m%.txt
set /a m=%m%+1
goto s
I wanted to be able to use a set /p option and without disturbing/stopping the loop so the animation plays while a user is typing in the set /p input. I think there is a way to do it with FOR but I'm not sure how. Any ideas? Thanks.
Although this topic is somewhat old, I just discovered it. This is a pure Batch file solution that works pretty well:
EDIT: I slightly modified the code in order to made it simpler.
#echo off
setlocal EnableDelayedExpansion
if "%1" equ "Animate" goto %1
for /F %%a in ('echo prompt $H ^| cmd') do set "BS=%%a"
for /F %%a in ('copy /Z "%~F0" NUL') do set "CR=%%a"
cd . > input.txt
start "" /B "%~F0" Animate
set "input="
:nextKey
set "key="
for /F "delims=" %%K in ('xcopy /W "%~F0" "%~F0" 2^>NUL') do if not defined key set "key=%%K"
if "!key:~-1!" equ "!CR!" goto endInput
if "!key:~-1!" equ "!BS!" (
if defined input set "input=%input:~0,-1%"
) else (
set "input=%input%!key:~-1!"
)
set /P "=%input%" > input.txt < NUL
goto nextKey
:endInput
del input.txt
echo/
echo/
echo Input read: "%input%"
goto :EOF
:Animate
set "banner= Enter your name please "
set m=0
:loop
if not exist input.txt exit
set /A m=(m+1)%%51
cls
echo/
echo/ !banner:~%m%,31!
echo/
echo/
if exist input.txt (type input.txt) else exit
ping -n 1 -w 300 localhost > NUL
ping -n 1 -w 300 localhost > NUL
ping -n 1 -w 300 localhost > NUL
goto loop
In this solution the animated "logo" is replaced by a banner, but the method to display a series of files is practically the same.
EDIT: This is possible in batch. See Aacini's answer.
This is not possible with batch files. Batch commands are single-threaded. To run two things simultaneously requires two instances of cmd.exe. But the console subsystem only allows one program to own the console at a time, so if the second instance of cmd is attached to the same console, one of them must be blocked.
It is possible to do something like this with a win32 executable which uses WriteConsoleOutput to modify the characters on the console screen. If you do that, you are no longer limited to just dumping text files, but the downside is that it's a lot more work than calling type in batch.
Example:
:loop
set n=0
set m=254
set /a n+=1
ping -n 1 -w 500 xxx.xxx.xxx.%n% | find /i "reply" > file
=====BELOW is what I need=====
set a=0
set /a a+=1
set %a%= < file
====ABOVE is what I need=====
if %n% lss %m% goto loop
So specifically I need a batch script that can make number of variables as much as he loops. I searched a lot for answer and even tried few ideas on my own... but I can't figure this out... I guess lack of batch knowledge since I am ubuntu user and not Win. Thanks in advance. Regards
Use FOR /L instead of SET /A with GOTO
Use FOR /F to process results of command instead of temp file and SET /P
Use carefully constructed variable names to emulate an array (potentially sparse array in this case)
for /l %%N in (1 1 255) do (
for /f "delims=" %%A in (
'ping -n 1 -w 500 xxx.xxx.xxx.%%N^|find /i "reply"'
) do set "addr[%%N]=%%A"
)
#echo off
setlocal enableextensions disabledelayedexpansion
for /l %%n in (1 1 254) do (
for /f "tokens=*" %%r in (
'ping -n 1 -w 500 xxx.xxx.xxx.%%n ^| find "reply" '
) do set "a[%%n]=%%r"
)
set a[
endlocal
This uses for /f to run a command (ping | find) and assing the output of the command (1 line of the ping response, filtered by find) to a variable with a incrementing number in its name.
set a[ is used to show the resulting data on console
#echo off
if exist Pingresult.txt del Pingresult.txt
for /l %%n in (1 1 254) do ping -n 1 -w 500 xxx.xxx.xx.%%n | find /i "reply" >>PingResult.txt