CMD start .exe with just one of multiple parameters - powershell

I would like my batch script to randomly choose one parameter on its own (from around 70 parameters eg. param1 - param70), without my input.
In addition to the random param, the exe has more parameters which always stay the same.
I dont know how to put this in code.
Here's an example of my thought:
param1=--abc
param2=--mno
param3=--xyz
./example.exe --hello --world --(param1 OR param2 OR param3)
which equals to:
./example.exe --hello --world --abc
or
./example.exe --hello --world --mno
or
./example.exe --hello --world --xyz

This can work in batch.You need to set each param though.
set /a numb=%random% %% 3
goto :param%numb%
:param0
Set "var=abc"
Goto :execute
:param1
Set "var=mno"
Goto :execute
:param2
Set "var=xyz"
Goto :execute
:execute
.\example.exe --hello --%var%
For 70 params you need to change %% 3 to %% 70

In powershell:
$params = "abc","mno","xyz"
& example.exe --hello --world --$(Get-Random -InputObject $params -Count 1)

Handling 70 parameters Gerhards way will get tedious. I'd build a parameter array and get a random one.
:: Q:\Test\2018\04\27\SO_50059458.cmd
#Echo off&SetLocal EnableExtensions EnableDelayedExpansion
Rem Build param[] array and count params
Set Cnt=-1&Set "param= abc bcd cde def efg fgh ghi hij ijk jkl klm lmn mno"
Set "param=%param: ="&Set /a Cnt+=1&Set "param[!Cnt!]=%"
:: show array
Set param
:: get random # in Cnt
Set /a Rnd=%Random% %% Cnt
echo Random %Rnd% out of %Cnt%
Echo .\example.exe --hello --!param[%Rnd%]!
Sample output:
> Q:\Test\2018\04\27\SO_50059458.cmd
param[0]=abc
param[10]=klm
param[11]=lmn
param[12]=mno
param[1]=bcd
param[2]=cde
param[3]=def
param[4]=efg
param[5]=fgh
param[6]=ghi
param[7]=hij
param[8]=ijk
param[9]=jkl
Random 10 out of 12
.\example.exe --hello --klm

Related

A code to take an amount of others in a string of lines

Before I begin, I would include this link to the problem in a word document, with highlighted texts, so the problem would be much clearer
https://archive.org/download/batfile10112019/bat%20file%2010112019.rar
*0000000000003000345800483854651180013732112019 0
*000000000010004466170000003000083BOUBADJA SAFIA 1
*000000000010010346810000003110730BOUKHEMKHEM NABILA 1
*000000000010010694160000000000806ROUIBAH MESSAOUDA 1
*000000000010014708210000000000999SETILA AFAF 1
*000000000010024010600000003176161ZAITER EP BOUHAROUD SOUAD 1
*000000000010054726551524653176161BOULASSEL NORA 1
Let’s suppose I have the above text file that contains lines, the length of each line is 62 (a combination of characters and spaces, you could verify by placing the cursor before the « * » character and count till the last character). I want to keep the header as it is, but for the other lines, I want a batch file (.bat) that will do the following :
Keep the header as it is ( as I mentioned above).
It will take 10.00 (unit of money, whether it’s euro, dollar etc…) out of each amount in the lines, the amount of each line begins from position « 22 » to position « 34 », so the amount of :
The second line is : 30000.83
The third line is : 31107.30
The fourth line is : 8.06
The fifth line is : 9.99
The sixth line is : 31761.61
The seventh line is : 15246531761.61
We can’t take 10.00 (dollars or euro or whatever…) out of the amounts of the fourth and the fifth lines which are 8.06 and 9.99 respectively, so the batch file will keep them as they are.
But for the amounts of the second, third, sixth and the seventh line will be changed as follows:
The second line is : 29990.83
The third line is : 31097.30
The fourth line is : 8.06
The fifth line is : 9.99
The sixth line is : 31751.61
The seventh line is : 15246531751.61
So the output file will look like this :
*0000000000003000345800483854651180013732112019 0
*000000000010004466170000002999083BOUBADJA SAFIA 1
*000000000010010346810000003109730BOUKHEMKHEM NABILA 1
*000000000010010694160000000000806ROUIBAH MESSAOUDA 1
*000000000010014708210000000000999SETILA AFAF 1
*000000000010024010600000003175161ZAITER EP BOUHAROUD SOUAD 1
*000000000010054726551524653175161BOULASSEL NORA 1
I have another problem when I deal with larger text file (15000 lines)
A friend helped me, but there were some errors in the code, that's why i included the above link in a word document to see the error message when dealing with text files that contain more than 10000 lines.
the code is:
#echo off
setlocal enableextensions enabledelayedexpansion
chcp 28591 >nul
set nouveau=modified.txt
echo. > %nouveau%
for /f "usebackq delims=" %%A in ("original file.txt") do (
set "line=%%A"
set "index=!line:~-1!"
if !index! EQU 1 (
set "account=!line:~0,21!"
set "amount=!line:~21,13!"
set "number=!line:~21,9!"
set "cut=!line:~30,4!"
set "client=!line:~34!
call :zeros amount
if !amount! GEQ 1000 (
set /a cut=!cut!-1000
set cut=000!cut!
set cut=!cut:~-4!
)
echo.!account!!number!!!cut!!client!
) else (echo.!line!)
) >> %nouveau%
exit
:zeros
set "chaine=!%1!"
for /L %%E in (0,1,12) do (
if not "!chaine:~%%E,1!"=="0" (set "%1=!chaine:~%%E!" & goto :eof)
)
goto :eof
I hope that I can take any amount I want from any line
(10.00 in this example).
If I want to change it to 5.00, is it possible to change simply the value 10.00 to 5.00 in the provided code.
thanks in advance for any help from you guys
You have a logical flaw (using the last four digits only for calculation). Probably you did this to work around the INT32 limit of set /a, but it will cause false results in some cases. You have to calculate with the whole amount. As cmd isn't able to do this, use the help of another language (I chose PowerShell here). The downside is poor performance because PowerShell has to be loaded for each calculation.
#echo off
setlocal enableextensions enabledelayedexpansion
chcp 28591 >nul
set nouveau=modified.txt
break> %nouveau%
(for /f "usebackq delims=" %%A in ("original file.txt") do (
set "line=%%A"
set "index=!line:~-1!"
if !index! EQU 1 (
set "account=!line:~0,21!"
set "amount=!line:~21,13!"
set "client=!line:~34!
REM strip leading zeros:
for /f "tokens=* delims=0" %%a in ("!amount!") do set cut=%%a
if !cut! geq 1000 (
for /f %%b in ('powershell "if (!cut! -ge 1000) {!cut!-1000} else {!cut!}"') do set "cut=0000000000000%%b"
set cut=!cut:~-13!
) else set cut=!amount!
echo !account!!cut!!client!
)
))>"%nouveau%"
goto :eof
Your original code is not just wrong, but also very inefficient... In order to perform the subtraction using the 9-digits limit of set /A command, you may split the operation in two parts: the low order (right side) 7 digits of the number plus the high part (left side) remaining 6 digits. The result is a pure Batch file that should run fast even over a file 15000 lines long.
#echo off
setlocal EnableDelayedExpansion
rem "subtract" may have maximum 7 digits including two decimal digits
set "subtract=1000"
set "nouveau=modified.txt"
set "subtract=0000000%subtract%"
set "subtract=1%subtract:~-7%"
set /P "header=" < "original file.txt"
(
echo %header%
for /F "skip=1 usebackq delims=" %%A in ("original file.txt") do (
set "line=%%A"
set "high=1!line:~21,6!" & set "low=1!line:~27,7!"
set /A "lowN=low-subtract"
if !lowN! geq 0 (
set /A "low=10000000+lowN"
) else (
set /A "highN=high-1000001"
if !highN! geq 0 (
set /A "high=1000000+highN, low=20000000+lowN"
)
)
echo !line:~0,21!!high:~1!!low:~1!!line:~34!
)
) > "%nouveau%"
If you're okay with using powershell, then you could probably just use a simple .ps1 script:
$Minus = 10.00
$LineNo = 1
Get-Content ".\original file.txt" | ForEach {
If ($LineNo -Eq 1) {$_} ElseIf ($LineNo -GT 1) {
[Decimal]$Decimal = $_.Substring(21,11)+"."+$_.Substring(32,2)
If ($Decimal-$Minus -LT 0) {$Result = $_.Substring(21,13)} Else {
$Result = (100*($Decimal-$Minus)).ToString("0000000000000")}
$_.SubString(0,21)+$Result+$_.SubString(34)}
$LineNo++} | Set-Content ".\modified.txt"
Just adjust $Minus as necessary.
Note: Get-Content may not be the quickest method to use if your files are very large.

How to convert binary to hex in Batch or Powershell?

I wondering if there is a way to convert binary to hexadecimal, in Batch or Powershell language.
Exemple :
10000100 to 84
01010101 to 55
101111111111 to BFF
In a simple way, I’m not very good in Batch or Powershell.
I will appreciate any kind of information
Converting a binary string to an integer is pretty straightforward:
$number = [Convert]::ToInt32('10000100', 2)
Now we just need to convert it to hexadecimal:
$number.ToString('X')
or
'{0:X}' -f $number
(pure batch)
#ECHO OFF
SETLOCAL
CALL :CONVERT 10000100
CALL :CONVERT 101111111111
CALL :CONVERT 1111111111
GOTO :EOF
:: Convert %1 to hex
:CONVERT
SET "data=%1"
SET "result="
:cvtlp
:: If there are no characters left in `data` we are finished
IF NOT DEFINED data ECHO %1 ----^> %result%&GOTO :EOF
:: Get the last 4 characters of `data` and prefix with "000"
:: This way, if there are only say 2 characters left (xx), the result will be
:: 000xx. we then use the last 4 characters only
=
SET "hex4=000%data:~-4%"
SET "hex4=%hex4:~-4%"
:: remove last 4 characters from `data`
SET "data=%data:~0,-4%"
:: now convert to hex
FOR %%a IN (0 0000 1 0001 2 0010 3 0011 4 0100 5 0101 6 0110 7 0111
8 1000 9 1001 A 1010 B 1011 C 1010 D 1101 E 1110 F 1111
) DO IF "%%a"=="%hex4%" (GOTO found) ELSE (SET "hex4=%%a")
:found
SET "result=%hex4%%result%"
GOTO cvtlp
This solution uses a parsing trick in the for %%a loop. The original value of hex4 is compared in the if and where the if fails, the value tested is assigned to hex4 so that when a match is found, the previous value tested remains in hex4.

Select Random Files From Txt File and Save to Another Txt - VBScript

I have a text file with 350.000+ lines. I need to select 100 random lines from that file and save them to a separate text file.
Is this possible with vbscript?
The file is UTF-8 will this be an issue?
I may need to do something more complex after this like: Select 100 random lines and save them to a text file from multiple text files (each containing 350k+ lines). Will this be achievable as well?
Sub Randomise
Randomize
Set rs = CreateObject("ADODB.Recordset")
With rs
.Fields.Append "RandomNumber", 4
.Fields.Append "Txt", 201, 5000
.Open
Do Until Inp.AtEndOfStream
.AddNew
.Fields("RandomNumber").value = Rnd() * 10000
.Fields("Txt").value = Inp.readline
.UpDate
Loop
.Sort = "RandomNumber"
Do While not .EOF
Outp.writeline .Fields("Txt").Value
.MoveNext
Loop
End With
End Sub
Randomises lines in a file.
Sub Cut
Set rs = CreateObject("ADODB.Recordset")
With rs
.Fields.Append "LineNumber", 4
.Fields.Append "Txt", 201, 5000
.Open
LineCount = 0
Do Until Inp.AtEndOfStream
LineCount = LineCount + 1
.AddNew
.Fields("LineNumber").value = LineCount
.Fields("Txt").value = Inp.readline
.UpDate
Loop
.Sort = "LineNumber ASC"
If LCase(Arg(1)) = "t" then
If LCase(Arg(2)) = "i" then
.filter = "LineNumber < " & LCase(Arg(3)) + 1
ElseIf LCase(Arg(2)) = "x" then
.filter = "LineNumber > " & LCase(Arg(3))
End If
ElseIf LCase(Arg(1)) = "b" then
If LCase(Arg(2)) = "i" then
.filter = "LineNumber > " & LineCount - LCase(Arg(3))
ElseIf LCase(Arg(2)) = "x" then
.filter = "LineNumber < " & LineCount - LCase(Arg(3)) + 1
End If
End If
Do While not .EOF
Outp.writeline .Fields("Txt").Value
.MoveNext
Loop
End With
End Sub
Can chop top 100 lines from a file.
Cut
filter cut {t|b} {i|x} NumOfLines
Cuts the number of lines from the top or bottom of file.
t - top of the file
b - bottom of the file
i - include n lines
x - exclude n lines
Example
filter cut t i 5 <"%systemroot%\win.ini"
---
Random
filter random
filter rand
Randomises lines of text in a file. Used to unsort a list.
Example
filter random < "%windir%\win.ini"
These are samples from another program. Common declarations are
Set Arg = WScript.Arguments
set WshShell = createObject("Wscript.Shell")
Set Inp = WScript.Stdin
Set Outp = Wscript.Stdout
General use is
Filter reads and writes standard in and standard out only. These are only available in a command prompt.
cscript filter <inputfile >outputfile
cscript filter <inputfile | other_command
other_command | cscript filter >outputfile
other_command | cscript filter | other_command
t
This is the batch file I use to call the above functions. The batchfile installs itself into the path if needed. This allows the vbs script (filter.vbs) to be used in a command prompt as if it's an exe file.
#echo off
Rem Make sure filter.vbs exists
set filter=
set filterpath=
Call :FindFilter filter.vbs
Rem Add filter.bat to the path if not in there, setx fails if it's already there
setx path %~dp0;%path% 1>nul 2>nul
Rem Test for some command line parameters
If not "%1"=="" goto main
echo.
echo -------------------------------------------------------------------------------
echo.
echo Filter.bat
echo ==========
echo.
echo The Filter program is a vbs file for searching, replacing, extracting, and
echo trimming console output and text files.
echo.
echo Filter.bat makes Filter.vbs easily usable from the command line. It
echo controls unicode/ansi support and debugging.
echo.
echo Type Filter Help or Filter HTMLHelp for more information.
echo.
cscript //nologo "%filter%" menu
Goto :EOF
:Main
echo %date% %time% %~n0 %* >>"%~dp0\FilterHistory.txt"
rem echo Batch file ran
rem echo %*
Rem /ud Unicode and Debug
If %1==/ud FOR /F "tokens=1*" %%i IN ("%*") DO cscript "%filter%
" //nologo //u //x %%j&Goto :EOF
Rem /u Unicode
If %1==/u FOR /F "tokens=1*" %%i IN ("%*") DO cscript "%filter%
" //nologo //u %%j&Goto :EOF
Rem /d Ansi Debug
If %1==/d FOR /F "tokens=1*" %%i IN ("%*") DO cscript "%filter%
" //nologo //x %%j&Goto :EOF
Rem -ud Unicode and Debug
If %1==-ud FOR /F "tokens=1*" %%i IN ("%*") DO cscript "%filter%
" //nologo //u //x %%j&Goto :EOF
Rem /u Unicode
If %1==-u FOR /F "tokens=1*" %%i IN ("%*") DO cscript "%filter%
" //nologo //u %%j&Goto :EOF
Rem -d Ansi Debug
If %1==-d FOR /F "tokens=1*" %%i IN ("%*") DO cscript "%filter%
" //nologo //x %%j&Goto :EOF
Rem ANSI
cscript "%filter%
" //nologo %*&Goto :EOF
Goto :EOF
:FindFilter
If Exist "%~dpn0.vbs" set filter=%~dpn0.vbs&set filterpath=%~dp0&goto :EOF
echo find filter 1
If Not "%~dpnx$PATH:1" == "" set filter=%~dpnx1&set filterpath=%~dp1&goto :EOF
echo find filter 2
If Exist "%temp%\filter.vbs" set filter=%temp%\filter.vbs&set filterpath=%temp%&goto :EOF
copy "%~dpnx0" "%~dpn0.bak"
if not errorlevel 1 (
echo creating "%~dpn0.vbs"
goto :EOF
)
copy "%~dpnx0" "%temp%\filter.bak"
echo Error %errorlevel%
if not errorlevel 1 (
echo creating "%temp%\filter.bak"
Goto :EOF
)
Goto :EOF
I solved this like this:
randomize
set objFSO = CreateObject("Scripting.FileSystemObject")
Set numberDic = CreateObject("Scripting.Dictionary")
set objInFile = objFSO.OpenTextFile("C:\Users\Mega\Desktop\250kWords.txt", 1, true, 0)
set objOutFile = objFSO.OpenTextFile("C:\Users\Mega\Desktop\100WordsSelected.txt", 2, true, 0)
strLines = objInFile.ReadAll
arrLines = split(strLines, vbNewLine)
intUpperLimit = ubound(arrLines)
numPicks = 100
'number of random picks must be less than or
'equal to the number of lines in the input file
if intUpperLimit < numPicks then
numPicks = intUpperLimit
end if
Do Until numberDic.Count = numPicks
index = int(rnd() * intUpperLimit) + 1
intRandom = arrLines(index)
intRandom = Trim(intRandom)
'if blank lines exist in text file, don't add them
if intRandom <> "" then
'if the line chosen is not in the dictionary object, add it
if not numberDic.exists(intRandom) then
numberDic.Add intRandom, intRandom
end if
end if
Loop
for each item in numberDic
objOutFile.WriteLine item
next
objInFile.close
objOutFile.close

Error with FOR LOOP in BAT FILE (WINDOWS)

Here is a for loop in a bat file, this loop takes numbers 1 through 100 and uses the mod operator on each integer. Im having difficulty calculating the average after the loop ends? can someone help me out with this? I have tried these statement:
echo VAR / 100
echo !VAR! / 100
SET /A TOTAL=%VAR% / 100
none work.
the following is the current code i have:
for /L %%i in (1, 1, 100) do (
SET /A VAR=%%i %% 5
SET /A TOTAL=%VAR% / 100
echo !VAR!
echo !TOTAL!
echo. >> results.txt
Try
SET /A TOTAL=!VAR! / 100
!var! returns the RUN-TIME value of var. %var% returns the PARSE-TIME value (ie. BEFORE the statement was executed)
(provided, of course, that you've already executed a
SETLOCAL ENABLEDELAYEDEXPANSION
instruction)

Date arithmetic in cmd scripting

I need to write a script to change a filename from aDate.txt to bDate.txt where:
aDate is the current system date in yyyymmdd format and
bDate is the current system date - 1 in yyyymmdd format.
I currently have:
set yy=%date:~6,2%
set mm=%date:~3,2%
set dd=%date:~0,2%
if "%date:~6,1%"==" " set yy=0%yy:~1,1%
if "%date:~3,1%"==" " set mm=0%mm:~1,1%
if "%date:~0,1%"==" " set dd=0%dd:~1,1%
SET sys_date=20%yy%%mm%%dd%
ECHO %sys_date%
REM still have to do this bit properly
SET sys_date_yesterday=%sys_date%a
move %sys_date%.txt %sys_date_yesterday%.txt
but I have no idea how to do the date -1 thing (other than the long winded) subtract 1 from the day and if that is = 0 then subtract one from the month and set the day = to the last day of the new month and so on for years.
Any ideas?
You have to do it the difficult way. I suggest to use this solution by SteveGTR. I copy the text below, because at least at least I cannot always see the solution on that site.
Here's a batch file I developed to subtract any number of days from the current date. It accepts a command line parameter of the number of days. The default is 1 day (yesterday):
#echo off
set yyyy=
set $tok=1-3
for /f "tokens=1 delims=.:/-, " %%u in ('date /t') do set $d1=%%u
if "%$d1:~0,1%" GTR "9" set $tok=2-4
for /f "tokens=%$tok% delims=.:/-, " %%u in ('date /t') do (
for /f "skip=1 tokens=2-4 delims=/-,()." %%x in ('echo.^|date') do (
set %%x=%%u
set %%y=%%v
set %%z=%%w
set $d1=
set $tok=))
if "%yyyy%"=="" set yyyy=%yy%
if /I %yyyy% LSS 100 set /A yyyy=2000 + 1%yyyy% - 100
set CurDate=%mm%/%dd%/%yyyy%
set dayCnt=%1
if "%dayCnt%"=="" set dayCnt=1
REM Substract your days here
set /A dd=1%dd% - 100 - %dayCnt%
set /A mm=1%mm% - 100
:CHKDAY
if /I %dd% GTR 0 goto DONE
set /A mm=%mm% - 1
if /I %mm% GTR 0 goto ADJUSTDAY
set /A mm=12
set /A yyyy=%yyyy% - 1
:ADJUSTDAY
if %mm%==1 goto SET31
if %mm%==2 goto LEAPCHK
if %mm%==3 goto SET31
if %mm%==4 goto SET30
if %mm%==5 goto SET31
if %mm%==6 goto SET30
if %mm%==7 goto SET31
if %mm%==8 goto SET31
if %mm%==9 goto SET30
if %mm%==10 goto SET31
if %mm%==11 goto SET30
REM ** Month 12 falls through
:SET31
set /A dd=31 + %dd%
goto CHKDAY
:SET30
set /A dd=30 + %dd%
goto CHKDAY
:LEAPCHK
set /A tt=%yyyy% %% 4
if not %tt%==0 goto SET28
set /A tt=%yyyy% %% 100
if not %tt%==0 goto SET29
set /A tt=%yyyy% %% 400
if %tt%==0 goto SET29
:SET28
set /A dd=28 + %dd%
goto CHKDAY
:SET29
set /A dd=29 + %dd%
goto CHKDAY
:DONE
if /I %mm% LSS 10 set mm=0%mm%
if /I %dd% LSS 10 set dd=0%dd%
echo Date %dayCnt% day(s) before %CurDate% is %mm%/%dd%/%yyyy%
Good Luck,
Steve
Easily Add or Subtract Days from a Date with a Windows Batch Script
Here's a solution I came up with for calculating date (add or subtract) with a batch script. Set the variables accordingly for your needs and then adjust the logic as need for your needs as well. This works very well for my needs and it's all contained to the same one batch script without too much logic.
To add: You can also use this script to add a number of days to the current date by deleting the minus (-)
symbol from the below batch script in the :DynamicVBSScriptBuild routine, so where you see this,-%MinusDay%, you simple remove the minus symbol to get ,%MinusDay%, on each of those lines and now the MinusDay= variable value will equal the number of days you want to add.
Important Note: It seems that five 9's (99999) is the limit on the batch script when subtracting with the MinusDays= value. It also seems that six 9's (999999) is the limit on the batch script when adding with the MinusDays= value.
Batch Script
#ECHO ON
::// Minus days is the number of days to subtract from the CURRENT DAY i.e. 2 for minus 2 days or 99999 for minus 99999 days from when it's run
SET MinusDay=2
:: This calls the temp vbs script routine that will be used to set YYYY-MM-DD values for the subtracted days date you specify
CALL :DynamicVBSScriptBuild
FOR /F "TOKENS=*" %%A IN ('cscript//nologo "%YYYYTmpVBS%"') DO SET YYYY=%%A
FOR /F "TOKENS=*" %%A IN ('cscript//nologo "%MMTmpVBS%"') DO SET MM=%%A
FOR /F "TOKENS=*" %%A IN ('cscript//nologo "%DDTmpVBS%"') DO SET DD=%%A
::// Set your web server log file path in the below variable
SET WebServerLogPath=C:\WebServer\Logs
::// Set web server log file name where YYYY MM DD variables are set to the values after the day numbers setup above are subtracted
SET YYYY=%YYYY%
SET MM=%MM%
SET DD=%DD%
ECHO %YYYY%%MM%%DD%
PAUSE
GOTO EOF
:DynamicVBSScriptBuild
SET YYYYTmpVBS=%temp%\~tmp_yyyy.vbs
SET MMTmpVBS=%temp%\~tmp_mm.vbs
SET DDTmpVBS=%temp%\~tmp_dd.vbs
IF EXIST "%YYYYTmpVBS%" DEL /Q /F "%YYYYTmpVBS%"
IF EXIST "%MMTmpVBS%" DEL /Q /F "%MMTmpVBS%"
IF EXIST "%DDTmpVBS%" DEL /Q /F "%DDTmpVBS%"
ECHO dt = DateAdd("d",-%MinusDay%,date) >> "%YYYYTmpVBS%"
ECHO yyyy = Year(dt) >> "%YYYYTmpVBS%"
ECHO WScript.Echo yyyy >> "%YYYYTmpVBS%"
ECHO dt = DateAdd("d",-%MinusDay%,date) >> "%MMTmpVBS%"
ECHO mm = Right("0" ^& Month(dt),2) >> "%MMTmpVBS%"
ECHO WScript.Echo mm >> "%MMTmpVBS%"
ECHO dt = DateAdd("d",-%MinusDay%,date) >> "%DDTmpVBS%"
ECHO dd = Right("0" ^& Day(dt),2) >> "%DDTmpVBS%"
ECHO WScript.Echo dd >> "%DDTmpVBS%"
GOTO EOF
Further Resources
FOR /F
CSCRIPT
WSCRIPT
DateAdd
Right
I needed something that would subtract days from the current date while checking leap years, etc. and this worked great.
I just call it from those scripts with the needed parameter (number of days to subtract), and then have it call back the calling script with substitutions and pass a parameter back to the original script for the modified (subtracted) date.
Here are examples:
Script needing date calculation variable set:
IF "%1"=="" goto modifydate
:modifydate
SET subtractdays=5
SET ModDateScript=\\servershare\path\Called_Scripts\ModDate.cmd
CALL "%ModDateScript%" %subtractdays% "%~fnx0"
Script which will calculate and pass back a %moddate% parameter to the original calling script to be set as a variable for it to process accordingly. You will simply put this at the end of the script you call to modify/subtract days from the current date (ModDate.cmd).
SET moddate=%mm%/%dd%/%yyyy%
Call %2 %moddate%
GOTO EOF
I was able to test and determine that these lines from the original script posted:
set yyyy=
set $tok=1-3
for /f "tokens=1 delims=.:/-, " %%u in ('date /t') do set $d1=%%u
if "%$d1:~0,1%" GTR "9" set $tok=2-4
for /f "tokens=%$tok% delims=.:/-, " %%u in ('date /t') do (
for /f "skip=1 tokens=2-4 delims=/-,()." %%x in ('echo.^|date') do (
set %%x=%%u
set %%y=%%v
set %%z=%%w
set $d1=
set $tok=))
if "%yyyy%"=="" set yyyy=%yy%
if /I %yyyy% LSS 100 set /A yyyy=2000 + 1%yyyy% - 100
Can be replaced with just this one single line and it works just as well:
FOR /F "tokens=2-4 delims=/ " %%A IN ("%date%") DO SET "mm=%%A" DO (& SET "dd=%%B") DO (& SET "yyyy=%%C")
Please explain what those lines (the ones I changed to just the one line with and statements) do anyways because I cannot tell the difference quickly testing. I subtracted back to the 19th century and it appeared accurate to me. I thought perhaps it helped handle the calculations where the modified year would be less than 2000 -- but I didn't see that unless I'm missing something.
Otherwise this one script can be easily called and pass back the %mm%/%dd%/%yyyy% as a parameter for several scripts which need their own calculations. Great and very efficient batch solution. I can pass the argument as %1, %2, %3, etc. and still use the setlocal in that script for the current date -- just make a variable something like moddate=%1, etc.
Lastly, I challenge any batch script expert to optimize this script even further and post back the results for batch people to test.
Thanks,
P
Try with this code in other words. You could use as a script subroutine or use this with the CALL and parameters functions to pass back to the original batch file:
:: Pass 1st parameter as number of days (whole numbers) to subtract from current day in date
:: This script is able to subtract days to any date of the current date
:: This script will check for leap years, etc. as well
#echo on
::for /f "tokens=2-4 delims=/ " %%A in ("%date%") do set "mm=%%A" do & set "dd=%%B" do & set "yyyy=%%C"
set "mm=%date:~4,2%" & set "dd=%date:~7,2%" & set "yyyy=%date:~10,4%"
set CurDate=%mm%/%dd%/%yyyy%
set dayCnt=%1
if "%dayCnt%"=="" set dayCnt=1
:: Substract your days here
set /A dd=1%dd% - 100 - %dayCnt%
set /A mm=1%mm% - 100
:CHKDAY
if /I %dd% GTR 0 goto DONE
set /A mm=%mm% - 1
if /I %mm% GTR 0 goto ADJUSTDAY
set /A mm=12
set /A yyyy=%yyyy% - 1
:ADJUSTDAY
if %mm%==1 goto SET31
if %mm%==2 goto LEAPCHK
if %mm%==3 goto SET31
if %mm%==4 goto SET30
if %mm%==5 goto SET31
if %mm%==6 goto SET30
if %mm%==7 goto SET31
if %mm%==8 goto SET31
if %mm%==9 goto SET30
if %mm%==10 goto SET31
if %mm%==11 goto SET30
:: ** Month 12 falls through
:SET31
set /A dd=31 + %dd%
goto CHKDAY
:SET30
set /A dd=30 + %dd%
goto CHKDAY
:LEAPCHK
set /A tt=%yyyy% %% 4
if not %tt%==0 goto SET28
set /A tt=%yyyy% %% 100
if not %tt%==0 goto SET29
set /A tt=%yyyy% %% 400
if %tt%==0 goto SET29
:SET28
set /A dd=28 + %dd%
goto CHKDAY
:SET29
set /A dd=29 + %dd%
goto CHKDAY
:DONE
if /I %mm% LSS 10 set mm=0%mm%
if /I %dd% LSS 10 set dd=0%dd%
echo Date %dayCnt% day(s) before %CurDate% is %mm%/%dd%/%yyyy%
SET DirDate=%mm%/%dd%/%yyyy%
:: The %2 parameter is passed from the calling script as the full path and name of the file to call back
:: %2 equals %~fnx0
:: The dirdate variable is passed as parameter %1 back to the calling script
Call %2 %dirdate%
GOTO EOF
I'm going to look for a vb or something more efficient I can still incorporate or call from a batch to dynamically calculate dates.
Found this script on ss64.com: https://ss64.com/nt/syntax-datemath.html (license: https://ss64.com/docs/copyright.html)
You can keep it separate and call it from your batch files without cluttering your code, it will fill some environments variables with the operation result.
For example, this will subtract one day to the current date (on my system date is returned in the "dd/mm/yyyy" format):
set YY=%date:~-4,4%
set MM=%date:~-7,2%
set DD=%date:~-10,2
call datemath.bat %YY% %MM% %DD% - 1
echo year=%_yy_int%, month=%_mm_int%, day=%_dd_int%
echo padded date:%_ymd_str%, padded month:%_mm_str%, padded day:%_dd_str%
The script:
#ECHO off
SETLOCAL
:: DateMath, a general purpose date math routine
:: If DateMath detects an error, variable _dd_int is set to 999999.
SET v_dd_int=0
SET v_mm_int=0
SET v_yy_int=0
SET v_ymd_str=
SET v_mm_str=
SET v_dd_str=
IF "%3"=="" goto s_syntax
IF "%4"=="+" goto s_validate_year
IF "%4"=="-" goto s_validate_year
IF "%4"=="" goto s_validate_year
:s_syntax
echo:
echo DATEMATH SYNTAX:
echo _______________
echo:
echo DateMath will set the variables as listed below
echo 'str' variables include leading zeros e.g. "01"
echo 'int' variables leading zeros are stripped e.g. "1"
echo:
echo CALL DateMath YY MM DD - YY2 MM2 DD2
echo:
echo Will set variable _dd_int to the signed difference
echo between the 2 dates (measured in days)
echo:
echo:
echo CALL DateMath YY MM DD +/- Days
echo:
echo Will set the following variables to the result of
echo adding or substracting days from the initial date:
echo _ymd_str, _yy_int
echo _mm_str, _mm_int,
echo _dd_str, _dd_int
echo:
echo:
echo ___________________________________
pause
echo:
echo:
echo CALL DateMath YY MM DD
echo:
echo Will set the following variables:
echo _ymd_str, _yy_int
echo _mm_str, _mm_int,
echo _dd_str, _dd_int
echo:
echo ___________________________________
echo:
echo _ymd_str is in YYYYMMDD format.
echo:
echo _yy_int is in YYYY format, even if YY format was originally supplied.
echo This conversion is useful for FAT/NTFS file dates which are in YY format.
echo:
ENDLOCAL & SET /a _dd_int=999999
goto :eof
:s_validate_year
::strip leading zeros
SET v_yy=%1
if %v_yy:~0,1% EQU 0 set v_yy=%v_yy:~1%
:: Check for Y2K
IF %v_yy% LSS 100 IF %v_yy% GEQ 80 SET /A v_yy += 1900
IF %v_yy% LSS 80 SET /A v_yy += 2000
:: at this point v_yy contains a 4 digit year
::validate month and day
if %2 GTR 12 goto s_syntax
if %3 GTR 31 goto s_syntax
SET v_mm=%2
SET v_dd=%3
::strip leading zeros
if %v_mm:~0,1% EQU 0 set v_mm=%v_mm:~1%
if %v_dd:~0,1% EQU 0 set v_dd=%v_dd:~1%
:: Set the int variables
SET /a v_dd_int=%v_dd%
SET /a v_yy_int=%v_yy%
SET /a v_mm_int=%v_mm%
:: Determine which function to perform - ADD, SUBTRACT or CONVERT
If not "%6"=="" goto s_validate_2nd_date
if "%4"=="" goto s_convert_only
:: Add or subtract days to a date
SET /a v_number_of_days=%5
goto s_add_or_subtract_days
:s_convert_only
SET /a v_dd_int=%v_dd%
IF %v_dd% LEQ 9 (SET v_dd_str=0%v_dd%) ELSE (SET v_dd_str=%v_dd%)
IF %v_mm% LEQ 9 (SET v_mm_str=0%v_mm%) ELSE (SET v_mm_str=%v_mm%)
SET v_ymd_str=%v_yy%%v_mm_str%%v_dd_str%
ECHO DATEMATH - Convert date only (no maths)
goto s_end
::::::::::::::::::::::::::::::::::::::::::::::::::
:s_validate_2nd_date
If "%4"=="+" goto s_syntax
:: Subtracting one date from another ::::::
:: strip leading zero
SET v_yy2=%5
if %v_yy2:~0,1% EQU 0 set v_yy2=%v_yy2:~1%
if %v_yy2% GTR 99 goto s_validate2nd_month
if %v_yy2% GTR 49 goto s_prefix_2_1950_1999
if %v_yy2% LSS 10 goto s_prefix_2_2000_2009
SET v_yy2=20%v_yy2%
goto s_validate2nd_month
:s_prefix_2_2000_2009
SET v_yy2=200%v_yy2%
goto s_validate2nd_month
:s_prefix_2_1950_1999
SET v_yy2=19%v_yy2%
:s_validate2nd_month
::strip leading zeros
::SET /a v_yy2=%v_yy2%
if %v_yy2:~0,1% EQU 0 set v_yy2=%v_yy2:~1%
::v_yy2 now contains a 4 digit year
if %6 GTR 12 goto s_syntax
SET v_mm2=%6
if %7 GTR 31 goto s_syntax
SET v_dd2=%7
::strip leading zeros
::SET /a v_mm2=%v_mm2%
if %v_mm2:~0,1% EQU 0 set v_mm2=%v_mm2:~1%
::SET /a v_dd2=%v_dd2%
if %v_dd2:~0,1% EQU 0 set v_dd2=%v_dd2:~1%
call :s_julian_day %v_yy_int% %v_mm_int% %v_dd_int%
SET v_sumdays1=%v_JulianDay%
call :s_julian_day %v_yy2% %v_mm2% %v_dd2%
SET v_sumdays2=%v_JulianDay%
SET /a v_dd_int=%v_sumdays1% - %v_sumdays2%
ECHO DATEMATH - Subtracting one date from another = days difference
ECHO ~~~~~~
ECHO %v_dd_int%
ECHO ~~~~~~
goto s_end_days
::::::::::::::::::::::::::::::::::::::::::::::::::
:s_add_or_subtract_days
if /i "%4"=="+" goto s_add_up_days
:: Subtract all days ::::::
SET /a v_dd=%v_dd% - %v_number_of_days%
:s_adjust_month_year
if %v_dd% GEQ 1 goto s_add_subtract_days_DONE
SET /a v_mm=%v_mm% - 1
if %v_mm% GEQ 1 goto s_add_days_%v_mm%
SET /a v_yy=%v_yy% - 1
SET /a v_mm=%v_mm% + 12
goto s_add_days_%v_mm%
:s_add_days_2
SET /a v_dd=%v_dd% + 28
SET /a v_leapyear=%v_yy% / 4
SET /a v_leapyear=%v_leapyear% * 4
if %v_leapyear% NEQ %v_yy% goto s_adjust_month_year
SET /a v_dd=%v_dd% + 1
goto s_adjust_month_year
:s_add_days_4
:s_add_days_6
:s_add_days_9
:s_add_days_11
SET /a v_dd=%v_dd% + 30
goto s_adjust_month_year
:s_add_days_1
:s_add_days_3
:s_add_days_5
:s_add_days_7
:s_add_days_8
:s_add_days_10
:s_add_days_12
SET /a v_dd=%v_dd% + 31
goto s_adjust_month_year
:s_add_up_days
:: add all days ::::::
SET /a v_dd=%v_dd% + %v_number_of_days%
:s_subtract_days_
goto s_subtract_days_%v_mm%
:s_adjust_mth_yr
SET /a v_mm=%v_mm% + 1
if %v_mm% LEQ 12 goto s_subtract_days_%v_mm%
SET /a v_yy=%v_yy% + 1
SET /a v_mm=%v_mm% - 12
goto s_subtract_days_%v_mm%
:s_subtract_days_2
SET /a v_leapyear=%v_yy% / 4
SET /a v_leapyear=%v_leapyear% * 4
If %v_leapyear% EQU %v_yy% goto s_subtract_leapyear
if %v_dd% LEQ 28 goto s_add_subtract_days_DONE
SET /a v_dd=%v_dd% - 28
goto s_adjust_mth_yr
:s_subtract_leapyear
if %v_dd% LEQ 29 goto s_add_subtract_days_DONE
SET /a v_dd=%v_dd% - 29
goto s_adjust_mth_yr
:s_subtract_days_4
:s_subtract_days_6
:s_subtract_days_9
:s_subtract_days_11
if %v_dd% LEQ 30 goto s_add_subtract_days_DONE
SET /a v_dd=%v_dd% - 30
goto s_adjust_mth_yr
:s_subtract_days_1
:s_subtract_days_3
:s_subtract_days_5
:s_subtract_days_7
:s_subtract_days_8
:s_subtract_days_10
:s_subtract_days_12
if %v_dd% LEQ 31 goto s_add_subtract_days_DONE
SET /a v_dd=%v_dd% - 31
goto s_adjust_mth_yr
:s_add_subtract_days_DONE
SET /a v_dd_int=%v_dd%
SET /a v_mm_int=%v_mm%
SET /a v_yy_int=%v_yy%
IF %v_dd% GTR 9 (SET v_dd_str=%v_dd%) ELSE (SET v_dd_str=0%v_dd%)
IF %v_mm% GTR 9 (SET v_mm_str=%v_mm%) ELSE (SET v_mm_str=0%v_mm%)
SET v_ymd_str=%v_yy%%v_mm_str%%v_dd_str%
ECHO DATEMATH - add or subtract days from a date = new date
goto s_end
::::::::::::::::::::::::::::::::::::::::::::::::::
:s_julian_day
SET v_year=%1
SET v_month=%2
SET v_day=%3
SET /a v_month=v_month
SET /a v_day=v_day
SET /A a = 14 - v_month
SET /A a /= 12
SET /A y = v_year + 4800 - a
SET /A m = v_month + 12 * a - 3
SET /A m = 153 * m + 2
SET /A m /= 5
SET /A v_JulianDay = v_day + m + 365 * y + y / 4 - y / 100 + y / 400 - 32045
ECHO The Julian Day is [%v_JulianDay%]
goto :eof
::::::::::::::::::::::::::::::::::::::::::::::::::
:s_end
ECHO ~~~~~~~~~~~~
ECHO [%v_ymd_str%] YY=[%v_yy_int%] MM=[%v_mm_str%] DD=[%v_dd_str%]
ECHO ~~~~~~~~~~~~
:s_end_days
ENDLOCAL&SET /a _yy_int=%v_yy_int%&SET /a _mm_int=%v_mm_int%&SET /a _dd_int=%v_dd_int%&SET _ymd_str=%v_ymd_str%&SET _mm_str=%v_mm_str%&SET _dd_str=%v_dd_str%
Can be done with adding jscript code to a batch file.
Here's the dayAdder.bat that accepts only one argument - the days you want to add to the current date and prints the result:
#if (#X) == (#Y) #end /* JScript comment
#echo off
cscript //E:JScript //nologo "%~f0" %*
exit /b %errorlevel%
#if (#X)==(#Y) #end JScript comment */
var days=parseInt(WScript.Arguments.Item(0));
Date.prototype.addDays = function(days) {
var date = new Date(this.valueOf());
date.setDate(date.getDate() + days);
return date;
}
var date = new Date();
WScript.Echo(date.addDays(5));
WScript.Echo("Year: " + date.getFullYear());
WScript.Echo("Month: " + date.getMonth());
WScript.Echo("DayOfTeWEek: " + date.getDay());
examaple and output:
E:\scripts>dayAdder.bat 7
Sun Nov 8 16:27:48 UTC+0200 2020
Year: 2020
Month: 10
DayOfTeWEek: 2
DayOfTheMonth: 3
You can modify it in way that will be suitable for you.