Windows batch file timing bug - windows

I've used %time% for timing previously - at least I think I have. I have this weird
IF NOT "%1" == "" (
echo Testing: %1
echo Start: %time%
sqlcmd -S MYSERVER -i test_import_%1.sql -o "test_%1%.log"
sleep 3
echo End: %time%
)
I run this, and it prints:
Testing: pm
Start: 13:29:45.30
End: 13:29:45.30
In this case, my sql code is failing (different reason), but I figure the sleep 3 should make the time increment by 3 at least. Any ideas?
tx,
tff

This has something to do with (not) delayed expansion, but I don't remember how that works exactly. You can work around it by using a "subroutine" like this:
#echo off
if "%1" == "" (
call :doit
)
echo done
goto :eof
:doit
echo %time%
sleep 1
echo %time%
goto :eof
Output:
C:\temp>q
19:46:36.43
19:46:37.45
done
The "proper" way of doing this is probably something like (from this entry in Raymon Chen's blog):
setlocal enabledelayedexpansion
if "%1" == "" (
echo !time!
sleep 2
echo !time!
)
To "see" the problem with immediate expansion, just run this (without echo off):
if "%1" == "" (
echo %time%
sleep 2
echo %time%
)
Output (on Windows 7):
C:\temp>if "" == "" (
echo 19:48:31.95
sleep 2
echo 19:48:31.95
)
19:48:31.95
19:48:31.95
The variables are all expanded at the same time, when the if is parsed.

Pause doesn't accept a parameter at all. It won't fail, but it won't continue either. If all is right, you should see a prompt to press a key.
The time you get, is the time the script is started. Apparently the %time% environment variable is not updated during the execution of the script.

DOS doesn't have a "sleep" function. You need to add this to the end of your batch file (or something like this):
#ECHO off
TITLE Initial title
SET TITLETEXT=Sleep
:: start of script
CALL :sleep 5
:: rest of script
GOTO :END
:: Function
:sleep ARG
ECHO Pausing...
FOR /l %%a in (%~1,-1,1) do (TITLE %TITLETEXT% -- time left %%as&PING.exe -n 2 -w 1 127.0.0.1>nul)
EXIT /B 0
:END
pause
::this is EOF
I tested this code, it should work fine.

Related

Reference element by index in a list using Batch Script

Trying to obtain an element in a list by its index, using batch script. Here is the code:
#Echo off
setlocal EnableDelayedExpansion
set acc[0]=default
set acc[1]=Account_2
set acc[2]=Account_3
set acc[3]=Account_4
set acc[4]=Account_5
if exist interator.txt (
set /p i=<interator.txt
echo "read: !i!"
echo "!acc[%i%]!"
REM start cmd /c setx AWS_PROFILE !acc[%i%]!
REM start cmd /k python script.py
set /A i=i+1
(echo !i!)>interator.txt
echo "write: !i!"
) else (
(echo 0)>interator.txt
)
Output Received:
"read: 0"
""
"write: 1"
As setx requires the CMD session to be closed, for affect to take place. I am trying a different approach to automate some regular stuff.
Expected Output:
"read: 0"
"default"
"write: 1"
#Echo off
setlocal EnableDelayedExpansion
set "acc[0]=default
set "acc[1]=Account_2"
set "acc[2]=Account_3"
set "acc[3]=Account_4"
set "acc[4]=Account_5"
if exist q65771965.txt (
set /p i=<q65771965.txt
echo "read: !i!"
FOR %%a IN (acc[!i!]) DO (
ECHO "!%%a!"
echo start cmd /c setx AWS_PROFILE "!%%a!"
echo start cmd /k python script.py
)
set /A i=i+1
(echo !i!)
echo "write: !i!"
) else (
(echo 0)
)
GOTO :EOF
OK - small changes to allow this to work on my test environment:
Changed name of file from interator.txt to q65771965.txt (suits my environment)
Removed updating of data file so the modifications are shown on-screen.
Replaced REM start with ECHO start to show the start commands on-screen.
Subtle syntax-oriented change : Use set "var1=data" for setting values - this avoids problems caused by trailing spaces.
Significant change : insert a for loop to transfer indirect values to a metavariable (%%a) and use these.
Possibly-required : I don't use setx much, but I've some memory of the argument's needing to be "quoted"
The problem is, you used echo "%acc[!i!]%" within a codeblock. You need another layer of parsing, like call echo "%%acc[!i!]%%"
As an alternative, restructure your code, so the critical part isn't in a code block:
#Echo off
setlocal EnableDelayedExpansion
set acc[0]=default
set acc[1]=Account_2
set acc[2]=Account_3
set acc[3]=Account_4
set acc[4]=Account_5
if not exist interator.txt (
(echo 0)>interator.txt
goto :eof
)
set /p i=<interator.txt
echo "read: !i!"
echo "%acc[!i!]%"
set /A i=i+1
(echo !i!)>interator.txt
echo "write: !i!"
(this code is functionally identically to yours, just structured in another way)
(btw: it should probably iterator, not interator - but that's only spelling)

If statement in batch file - user chooses option

New to batch/sql files. Thanks for you help.
What im trying to do:
user picks option 1, runs my sql file.
user picks 2, exits program.
user enters nothing or invalid option, ECHO "invalid option".
Problem: anything I type will exit my program. What am I doing wrong?
ECHO 1 - Show Report
ECHO 2 - Exit
SET choice=""
SET /P input=Your choice:
IF "%input%"=="1" (
GOTO :sql file
) ELSE (
IF "%input%"=="2" (
GOTO :Exit
)
) ELSE (
IF "%input%"=="" (
ECHO Invalid option chosen.
)
)
PAUSE
Just use the choice command, its instructions are available by entering choice /? at the Command Prompt.
#ECHO OFF
ECHO 1 - Show Report
ECHO 2 - Exit
CHOICE /C 12 /M "Your choice"
IF ERRORLEVEL 2 GOTO :EOF
REM This line is your SQL report code
PAUSE
If you still wanted to use, what in your case I believe is the wrong Set /P input method, then something like this should be relatively robust, given that your end user is free to enter whatever they like as input, mischievous or harmful intent included:
#ECHO OFF
ECHO 1 - Show Report
ECHO 2 - Exit
:GETInput
SET "input="
SET /P "input=Your choice: "
2>&1 SET input | FINDSTR /XR "input=[12]" 1>NUL || (
ECHO Invalid option chosen
GOTO GETInput
)
IF %input% EQU 2 GOTO :EOF
REM This line is your SQL report code
PAUSE
There is one extract closing bracket [Line #12] inside nested if..else. Also, as far as i know, your label :sql file should not contain space and you must declare it inside the batch file (Same for label :Exit)
I did few changes in your code to make it work
#echo off
:Main
cls
ECHO 1 - Show Report
ECHO 2 - Exit
SET choice=""
SET /P input=Your choice:
IF "%input%"=="1" (
GOTO :SQLReport
) ELSE IF "%input%"=="2" (
GOTO :EOF
) ELSE (
ECHO.
ECHO Invalid option chosen.
pause
GOTO :Main
)
:SQLReport
ECHO.
ECHO Running SQL Report...
GOTO :EOF
:EOF

Append date to text file in MS DOS 6.22

I have been looking around and can't seem to find a solution. I'm a total newbie with Windows command line and scripting in general so I figure this is a great place to ask my question.
I'm basically trying to append a time stamp to my script assignments. We submit the batch scripts as text files and I wanted to put append a time stamp to the text document. I asked my professor and he said it was possible but he wasn't sure how to do it. I can't seem to find the solution that I am looking for online. I know how to do this in the windows command line, but not in on the commandline. Any help would be greatly appreciated!
rem This batch file copies all work to a batch file and then to com1:
#echo off
cls
cd \
cd menu
copy *.bat mywork.bat
echo This file was created on (this is where I run in to trouble)
type mywork.bat > com1:
cd \
cls
All Files have been copied.
These are all MSDOS methods and will mostly not work in default Windows.
Using Qbasic in a batch script:
#echo off
echo open "!_~_!.bat" for output as #1: a$=DATE$>!_~_!.bas
echo ? #1, "SET DAY="+RIGHT$(a$,2)+LEFT$(a$,2)+MID$(a$,4,2)>>!_~_!.bas
echo SYSTEM>>!_~_!.bas
qbasic /run !_~_!.bas
call !_~_!.bat
del !_~_!.bat
del !_~_!.bas
echo %day%
ren filename.xxx %day%.xxx
Native way to get the date
#echo off
echo exit|"%comspec%" /k prompt set d=$D$_|find /v "exit">"%temp%.\datetmp.bat"
for %%a in (call del) do %%a "%temp%.\datetmp.bat"
echo the date is %d%
Using an ASCII binary:
#echo off
:: ascii assembler line processing utility by Herbert Kleebauer
:: for the source code and usage information, use this URL
:: http://groups.google.com.au/groups?q=Usage:+edl
::
echo Bj#jzh`0X-`/PPPPPPa(DE(DM(DO(Dh(Ls(Lu(LX(LeZRR]EEEUYRX2Dx=>edl.com
echo 0DxFP,0Xx.t0P,=XtGsB4o#$?PIyU WwX0GwUY Wv;ovBX2Gv0ExGIuht6>>edl.com
echo ?#}I{uNWEF~NPCkaEFAKLCmaIj#KguHaEFCKYCmavh#{HM?cCiuGGwHmYz>>edl.com
echo CgisCGH`LbuuGNO#hRgco{W?dOGg#N?]gBgoG}G?X_SgONks?GN`LBgDu}>>edl.com
echo G?I_DgGNoG?w#jgLiuuroD#?FHoGpBBDcB?1?pIoCRaICSbICn}ExvHmE?>>edl.com
echo coF?DO~yanxCqap?#?lpZrH~sa`LyNHKqDGwQVTNG`CiECICtdL{D?{esL>>edl.com
echo ysICu_{OuD#sCREGHt~F#lgNHYq`EE{S~{Hq_gC{Lr#CE{HQ}#ExuCNQmB>>edl.com
echo BwjFCs?osqs?}n`LKLj?o{}HwJvClpCSEGt~~1}HGGHCSaCU}GiuJaxLCS>>edl.com
echo c}BWuNC_FE{sCkEGFAPqCmEGNAcQNJwLECuQsa{Oe~CK~CkqCmeGmEFbCN>>edl.com
echo C?kEFbBaCGH1jnjBrz?JAcqo~O~?lJgvxs~CspajF{oFEBHijnjBrz?JAc>>edl.com
echo vx~O~?QJLqos~CspFjN{xFEByijnj#ComJcIpCSAijZNUmJaujC{U]JaJB>>edl.com
echo CcClmCJ\jbCS]GFrj~CkEGjBSookVBA_#NJBHmClnEj1JYjxCoIBrh{BFC>>edl.com
echo HtdCWECaBsCC#ZgB#WgB}fj~BsMV#NgB~chvsb{Os{AR{msDUsycsk{SK{>>edl.com
echo VQ{ZsH\sQdsq{Sj{cAICNWl{~B1CNW_K~BxVkSfCA?Cb#N}W#{=sIfjBH}>>edl.com
echo G}N}NK}NNguM#[umCqBJqD#mzDCCClmCJFuhClmC{#jJSN?`CWEG{Cs#Pt>>edl.com
echo cc?AyAFZp{CkEGjBEpEFDNCCkq=jBktx{S[zDgsjCKtl{S]zDgjjCKtc{S>>edl.com
echo _zDgajCKtG{SazDgXjCKtL{SczDgOjCKtR{SezDgFjCKtX{SYzMgFICG?K>>edl.com
echo gF#FIE?EgF}ZhziEuRN~CK}~DqgLoqo?t_ogIKEh?{JU=fCguGiuz_FrCC>>edl.com
echo sCyOjEEsjwr~EvPK~CSqCt~FS}Ha}HCGxCUqERNG]CRQa_BfsCoaoy?h#x>>edl.com
echo CGJH?w``LRaDBBobc?q?a_q?C_0x>>edl.com
:: creates a variable in YYYYMMDD format
echo.!|edl "" "set date=$tY$ty$tm$td">temp.bat
call temp.bat
del temp.bat
echo %date%
del edl.com
:: $tY : year - leading 2 digits (20 for 2003)
:: $ty : year - trailing 2 digits (13 for 2013)
:: $tm : month - 2 digits
:: $td : day - 2 digits
:: $tH : hour - 2 digits in military time (23:00 is 11pm)
:: $tM : minute - 2 digits
:: $tS : second - 2 digits
Another MSDOS method that gives various date and time info:
:: D8TIME.BAT by Larry Nelson from BATPOWER Fidonet Echo
:: Modified 17/07/1995
#echo off
:: goto %1
:: Setup Magic.bat with %temp% in it withour CR/LF
echo %temp%>%temp%b4.bat
for %%x in (rcx 3 w q) do echo %%x>>%temp%b4.scr
:: ^ (2h=2 chars, 3h=3 chars, 4h=4 chars, etc.)
debug %temp%b4.bat<%temp%b4.scr>nul
:d8ti
echo set d8ti=%%3 %%4 >%temp%!.bat
echo y|copy %temp%b4.bat %temp%magic.bat>nul
dir %temp%!.bat |find "!" >>%temp%magic.bat
call %temp%magic.bat
:: goto L8r
:d8
echo set d8=%%3 >%temp%!.bat
echo y|copy %temp%b4.bat %temp%magic.bat>nul
dir %temp%!.bat |find "!" >>%temp%magic.bat
call %temp%magic.bat
:: goto L8r
:time
echo set time=%%4 >%temp%!.bat
echo y|copy %temp%b4.bat %temp%magic.bat>nul
dir %temp%!.bat |find "!" >>%temp%magic.bat
call %temp%magic.bat
:: goto L8r
:day
echo y|copy %temp%b4.bat %temp%magic.bat>nul
ver |date |find/i "current" >>%temp%magic.bat
echo set day=%%3 >%temp%current.bat
call %temp%magic.bat
:: goto L8r
:L8r
for %%q in (magic current ! b4) do if exist %temp%%%q.bat del %temp%%%q.bat
if exist %temp%b4.scr del %temp%b4.scr
set
pause
:: D8TIME.bat
:: Usage = d8time d8 (date) time (time) d8ti (date/time) day (day of week).
:: Datetime pulls system date and/or time, or day of the
:: week and puts it into an envar with current date/time,
:: date, or time. Find.exe must be in path. A sample usage
:: of Datetime is Bootlog.bat below. With { call bootlog }
:: in your Autoexec.bat a file named Bootlog.dat will
:: receive a record of every time your computer is booted up.
::
::BOOTLOG.BAT
::
:: #echo off
:: cls
:: call d8time d8ti
:: echo %d8ti% >>bootlog.dat
:: set d8ti=
:: :L8r
You can use the %DATE% and/or %TIME% variables:
> echo %DATE% %TIME%
2014-09-23 13:43:03.02
Alternatively, you can use the DATE and/or TIME commands:
> date /t
2014-09-23
> time /t
13:56
The /t switch means "don't prompt to set the date/time, just output the current value". You can pipe the output of the commands to a file like this:
date /t >> mywork.bat
The >> means append the output to the end of the file.
#echo off
setlocal
set "script=%~f0"
set "script=%script:\=\\%"
:: Define simple macros to support JavaScript within batch
set "beginJS=mshta "javascript:close(new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1).Write("
set "endJS=));""
set "JS=(new ActiveXObject('Scripting.FileSystemObject').GetFile('%script%')).DateCreated"
for /f %%N in (
'%beginJS% %JS% %endJS%'
) do set date_created=%%N
rem checks if time stamp function is created
call :getTimeStamp >nul 2>&1 || (
echo(>>"%~f0"
echo :getTimeStamp >>"%~f0"
echo echo created on %date_created% >>"%~f0"
echo goto :eof >>"%~f0"
)
endlocal
::::::::your code goes here
cls
cd \
cd menu
copy *.bat mywork.bat
::this line is changed
call :getTimeStamp
type mywork.bat > com1:
cd \
cls
All Files have been copied.
::::::::end of your code
goto :eof
EDIT
This is about a REAL dos.Just saw the comments bellow.
This will totally not work on DOS - no call :lablel , no MSHTA , no FOR /F ...
Despite I have no willingness to delete my answer - it was not so easy to get the creation date of the file ,and append a new subroutine (only if there is no already) that prints the date.At least was a good exercise .

BATCH call a label outside of batch script

I'm running a loop, whereby if a host (from a list) is online, a bunch of things happen to it. However, I want these things to happen independently to the main 'host checking' script, so that all hosts are processed almost concurrently.
Therefore, how can I achieve calling a label outside of the main batch script? I've tried variations of using the Start command to call :separatesub with no luck yet. Thanks in advance!
# ECHO Off
set a=19
if %a% == 1 (echo A is 1) else (start :separatesub)
pause
:separatesub
echo These actions will now be applied independently of the main batch script
:EOF
You should use arguments
The main batch file:
# ECHO Off
set a=19
if %a% == 1 (echo A is 1) else start MyLib.bat %a%
:EOF
The MyLib.bat file:
# ECHO Off
if %1% == 19 goto Label19
:EOF
I hope this will help
# ECHO Off
set a=19
if %a% == 1 (echo A is 1) else (Call yourbatchfile.bat separatesub )
if %a% == 2 (echo A is 2) else (Call yourbatchfile.bat otherfunction param1 param2 )
pause
Goto:EOF
...
The magic happens with Call:%* in yourbatchfile.bat
It will work as a library of functions
yourbatchfile.bat
Call:%*
Goto:EOF
:separatesub
...
Goto:EOF
:otherfunction
...
Goto:EOF

Why this code says echo is off?

What is wrong with this code? It says ECHO is off.
#ECHO off
set /p pattern=Enter id:
findstr %pattern% .\a.txt > result
if %errorlevel%==0 (
set var2= <result
echo %var2%
set var1=%var2:~5,3%
echo %var1% > test.txt
echo %var1%
) else (
echo error
)
del result
pause
Any help is appreciated.
If your variable is empty somewhere, it will be the same as having the command "echo" on its own, which will just print the status of echo.
To avoid this, you should replace all your echo commands with something like this:
echo var2: %var2%
That way, if %var2% is empty it will just print "echo var2:" instead of "echo off".
As Laurent stated, it's not a problem of the ECHO, it's a problem of your code.
In batch files, blocks are completely parsed before they are executed.
While parsing, all percent expansion will be done, so it seems that your variables can't be changed inside a block.
But for this exists the delayed expansion, the delayed expansion will be evaluated in the moment of execution not while parsing the block.
It must be enabled, as per default the delayed expansion is disabled.
#ECHO off
setlocal EnableDelayedExpansion
set /p pattern=Enter id:
findstr %pattern% .\a.txt > result
if %errorlevel%==0 (
set var2= <result
echo(!var2!
set var1=!var2:~5,3!
echo(!var1! > test.txt
echo(!var1!
) else (
echo error
)
del result
I used here the construct echo( instead of echo as this will ensure echoing an empty line even if the variable is empty.
Not sure, if this post is still read, but nevertheless.
You should try the following:
On top of the code right after #echo off you have to put in
setlocal enabledelayedexpansion
Additionally anywhere you want to use variables changed in a block of brackets (like For-Loops or If's) you have to change the %into ! to get
!varname!
This should be helping...
Greetings
geisterfurz007
First create a file a.txt in the same directory u have this batch file ... write some text in that...Note: only Windows 2000
Windows ME
Windows XP
Windows Vista
Windows 7 supports FINDSTR
set /p pattern=Enter id:
findstr %pattern% a.txt > __query.tmp
set /p result=<__query.tmp
if %errorlevel%==0 (
set var2= %result%
echo %var2%
set var1= %var2:~5,3%
echo %var1% > test.txt
echo %var1%
) else (
echo error
)
del __query.tmp
pause
run this bath file .. you will find a substring(start=5,length=3) of the first line of string you have in a.txt in a newly created file test.txt. Finally got it working !
The solution for your problem is to put the "echo"s after the if block is completed.
Try this:
#ECHO off
set /p pattern=Enter id:
findstr %pattern% .\a.txt > result
if %errorlevel%==0 (
set var2= <result
set var1=%var2:~5,3%
goto print
) else (
echo error
goto result
)
:print
echo %var2%
echo %var1% > test.txt
echo %var1%
:result
del result
pause
This way you can see the solution as you wanted.
Cheers! ;]

Resources