File has been modified in the last 15 mins -Batch Script - date

Hi I need help as I'm new to BatchScript.
I need to check if any file/folder within a directory has been modified in the last 15 mins.
Here's my logic :
Find last modified date
Find current date
Find if difference between these two is 15 mins.
I'm able to do the 1st 2 steps.I'm stuck with the third
Please help me to find the time difference between these 2 dates.
Or if there's a better/easier logic.
Here is my code:
#echo off
for /f %a in (' dir "D:\BatchFiles" /od/b/s/t') do set Date1= %~ta
echo The most recently created file is %Date1%
#echo off
for /f "delims=" %i in ('time /t') do set output=%i
#echo off
SET Date2= %DATE:~4,2%/%DATE:~7,2%/%DATE:~10,4% %output%
echo The current date is %Date2%
PAUSE

Here is a pure batch file that returns all files in a given directory of a given age, with the following restrictions:
dates are not resolved correctly, so if a file has been modified in the previous month, it might not be included in the result erroneously; in case the maximum age is to be defined in terms of days, a forfiles solution might be more reasonable;
files that have both characters ) and , in their paths will be missing in the output; this is because of a design flaw of the wmic command, which is used to retrieve locale-independent date/time information of the last modification of files;
To use the script -- let us call it max-aged-files.bat --, provide command line arguments like this:
max-aged-files.bat 15*60 "D:\BatchFiles"
The first argument is the maximal age of a file in terms of seconds; simple arithmetic expressions like 15*60 are understood. The second argument is the location and/or file pattern to apply for searching files; you can state a directory path like "D:\BatchFiles" here, or a file pattern like "*.bat", or a comination like "D:\BatchFiles\*.bat"; it you omit it, the current directory is used.
Here is the code:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem /* Please regard that this script cannot handle dates correctly!
rem so if current date and file date are in different months it fails! */
rem // Retrieve and prepare arguments:
set "MAXAGE=%~1" & rem // (maximum age of files in terms of seconds)
if defined MAXAGE (set /A "MAXAGE=%MAXAGE%+0") else (
>&2 echo ERROR: maximum age not specified! & exit /B 1
)
if %MAXAGE% GEQ 86400 (>&2 echo ERROR: maximum age exceeds range! & exit /B 1)
shift /1
set "LOCATION=%~1"
set "ATTR=%~a1"
set "ATTR=%ATTR:~,1%"
if not defined LOCATION (set "LOCATION=.\*.*") else (
if "%ATTR%"=="d" set "LOCATION=%LOCATION%\*.*"
)
rem /* Gather current date/time in standardised format
rem [like: `YYYYMMDDHHMMSS.UUUUUU+ZZZ`]: */
for /F "delims=" %%I in ('wmic OS GET LocalDateTime') do (
for /F "delims=" %%J in ("%%I") do set "CURRTIME=%%J"
)
rem // Extract `YYYYMMSS` portion from current date/time:
set "CURRDATE=%CURRTIME:~,8%"
rem // Extract `HHMMSS` portion from current date/time only:
for /F "delims=." %%T in ("%CURRTIME:~8%") do (
set "CURRTIME=%%T"
)
rem // Loop through all files at given location:
for %%F in ("%LOCATION%") do (
set "ITEM=%%~fF"
setlocal EnableDelayedExpansion
rem // Gather file date/time in standardised format:
for /F "delims=" %%E in ('
2^> nul wmic DataFile WHERE Name^="!ITEM:\=\\!" GET LastModified ^|^| ^
2^> nul wmic DataFile WHERE ^(Name^="!ITEM:\=\\!"^) GET LastModified
') do (
for /F "delims=" %%F in ("%%E") do set "FILETIME=%%F"
)
rem // Extract `YYYYMMSS` portion from file date/time:
set "FILEDATE=!FILETIME:~,8!"
rem // Extract `HHMMSS` portion from file date/time:
for /F "delims=." %%T in ("!FILETIME:~8!") do (
set "FILETIME=%%T"
)
rem // Compute date difference between file and current date:
set /A "DATEDIFF=CURRDATE-FILEDATE"
rem // Continue processing only if date difference is zero or one:
if !DATEDIFF! GEQ 0 if !DATEDIFF! LEQ 1 (
rem // Convert date difference to seconds:
set /A "DATEDIFF*=240000"
rem // Compute time difference, regarding also date difference:
set /A "TIMEDIFF=DATEDIFF+1!CURRTIME!-1!FILETIME!"
rem // Pad time difference to consist of 6 digits [like `HHMMSS`]:
set "TIMEDIFF=000000!TIMEDIFF!" & set "TIMEDIFF=!TIMEDIFF:~-6!"
rem // Convert time difference to seconds:
set /A "TIMEDIFF=1!TIMEDIFF:~-2!-100+60*(1!TIMEDIFF:~-4,-2!-100+60*(1!TIMEDIFF:~-6,-4!-100))"
rem // Return item if
if !TIMEDIFF! LEQ %MAXAGE% (
echo(!ITEM!
)
)
endlocal
)
endlocal
exit /B

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.

Comparing registry string value within a date range

I am writing a batch script which needs to compare registry data value string with ±3 days of todays date.
My REG QUERY returns a value:
HKEY_LOCAL_MACHINE\Software\Wow6432Node\KasperskyLab\Components\34\1103\1.0.0.0\Statistics\AVState
Protection_BasesDate REG_SZ 27-08-2018 08-53-00
I need to output to a file, depending if it is within the range or not.
Script:
REG QUERY "HKLM\Software\Wow6432Node\KasperskyLab\Components\34\1103\1.0.0.0\Statistics\AVState" /v "Protection_BasesDate" | Find "2018"
IF %ERRORLEVEL% == 1 goto end
If %ERRORLEVEL% == 0 goto makefile
:makefile
echo "{"product":"Override Antivirus","running":true,"upToDate":true}" > c:\ProgramData\CentraStage\AEMAgent\antivirus.json
:end
#exit
This solution takes this answer as base, so please review such an answer before post further questions here...
#echo off
setlocal EnableDelayedExpansion
rem Define the "Date to Julian Day Number" conversion function
set "DateToJDN(YMD)=( a=(YMD), y=a/10000, a%%=10000, m=a/100, d=a%%100, a=(m-14)/12, (1461*(y+4800+a))/4+(367*(m-2-12*a))/12-(3*((y+4900+a)/100))/4+d-32075 )"
rem Get the JDN of today's date minus/plus 3
for /F "tokens=2 delims==" %%t in ('wmic os get localdatetime /value') do set "dateTime=%%t"
set /A "todayMinus3=!DateToJDN(YMD):YMD=%dateTime:~0,8%!-3, todayPlus3=todayMinus3+6"
reg Get the date from REG QUERY command; the assumed output format is: Protection_BasesDate REG_SZ 27-08-2018 08-53-00
for /F "tokens=3-5 delims=- " %%a in (
'REG QUERY "HKLM\Software\Wow6432Node\KasperskyLab\Components\34\1103\1.0.0.0\Statistics\AVState" /v "Protection_BasesDate"'
) do set /A "BasesDate=!DateToJDN(YMD):YMD=%%c%%b%%a!"
if %BasesDate% geq %todayMinus3% if %basesDate% leq %todayPlus3% (
echo Date in range
)
There are many languages that can do much better than batch, but this might be a solution.
#echo off
set day=-3
for /f "delims=" %%i in ('reg query "HKLM\Software\Wow6432Node\KasperskyLab\Components\34\1103\1.0.0.0\Statistics\AVState" /v Protection_BasesDate" ^| findstr "2018"') do set "regdate=%%i"
for /f "tokens=1-3" %%a in ("%regdate%") do set "actual=%%c"
:check
echo >"%temp%\%~n0.vbs" s=DateAdd("d",%day%,now) : d=weekday(s)
echo>>"%temp%\%~n0.vbs" WScript.Echo year(s)^& right(100+month(s),2)^& right(100+day(s),2)
for /f %%a in ('cscript /nologo "%temp%\%~n0.vbs"') do set "result=%%a"
del "%temp%\%~n0.vbs"
set "yyyy=%result:~0,4%"
set "mm=%result:~4,2%"
set "dd=%result:~6,2%"
set "final=%dd%-%mm%-%yyyy%"
echo %final%
if %day% == 1 goto :EOF
if %actual% == %final% (echo Within 3 days!!) else (set /a day+=1 & goto :check)
We actually get the date of the system using cscript (yes I pipe to file, but you can run hybrid without the temp file) Then we take the past 3 days' dates and match them in the format of the registry key, if the key matches within 3 days, I just echo Within 3 days! There is also an if statement, if the day counter = 1, I exit the script, as we do not want to go into future and this loop forever if the counter if we do not stop it somewhere.
If it does work for you, you can simply remove the line print %final% and replace this line:
if %actual% == %final% (echo Within 3 days!!) else (set /a day+=1 & goto :check)
with this line:
if %actual% == %final% (echo "{"product":"Override Antivirus","running":true,"upToDate":true}" > "c:\ProgramData\CentraStage\AEMAgent\antivirus.json") else (set /a day+=1 & goto :check)

Find a number in text file and change signs for its row data using command line

I am learning batch scripting and the first task that came to me is a Text file that has more than 1000 rows and is something like this :
Organization, month,acct no.,data1,data2,data3,data4
orgA,Jan,1234,78900,78900,78900,78900
I need help in writing a batch file which should find a specific acct no. (for example: 3456) and put a '-' before data1, data2,data3,data4
I have tried :
1) using batch commands:
for /F "tokens=1 delims=," %%a in (%source%) do SET "org=%%a"
for /F "tokens=2 delims=," %%b in (%source%) do SET "month=%%b"
for /F "tokens=3 delims=," %%c in (%source%) do SET "acct=%%c"
for /F "tokens=4 delims=," %%d in (%source%) do SET "data1=%%d"
for /F "tokens=5 delims=," %%e in (%source%) do SET "data2=%%e"
for /F "tokens=6 delims=," %%f in (%source%) do SET "data3=%%f"
for /F "tokens=7 delims=," %%g in (%source%) do SET "data4=%%g"
set search=3456
set replace=-%data1%
FOR /F "tokens=* delims=," %%i in ("%source%") do
(set newline=%%i
IF /i %acct% EQU %search%
set newline=!newline:%org%,%month%,%acct%,%replace%!
echo !newline!>>%target%
)
2)VBS:
#echo objFile.WriteLine strNewText
#echo objFile.CloseConst ForReading =
#echo Const FileIn = "test.txt"
#echo Const FileOut = "test_adhoc.txt"
#echo Set objFSO = CreateObject("Scripting.FileSystemObject")
#echo Set objFile = objFSO.OpenTextFile(FileIn, ForReading)
#echo strText = objFile.ReadAll
#echo objFile.Close
#echo strNewText = Replace(strText, "*,*,3456,*,*,*,*", "*,*,3456,-*,-*,-*,- *")
#echo Set objFile = objFSO.OpenTextFile(FileOut, ForWriting)
#echo objFile.WriteLine strNewText
#echo objFile.Close
The problem with this type of management over large files is that Batch file processing is inherently slow, so any method that may speed up the process is good.
EDIT: Change the signs of the last four data.
2ND EDIT: ... when such a data may have decimal point
#echo off
setlocal EnableDelayedExpansion
set search=3456
rem Find the number of lines before the target one
for /F "delims=:" %%a in ('findstr /N "^.*,.*,%search%" source.txt') do set /A lines=%%a-1
rem Reading from the source file
< source.txt (
rem Copy the lines previous to target one
for /L %%i in (1,1,%lines%) do set /P "line=" & echo !line!
rem Read and process the target line
set /P "line="
for /F "tokens=1-7 delims=," %%a in ("!line!") do (
set "data1=-%%d" & set "data2=-%%e" & set "data3=-%%f" & set "data4=-%%g"
echo %%a,%%b,%%c,!data1:--=!,!data2:--=!,!data3:--=!,!data4:--=!
)
rem Copy the rest of lines
findstr "^"
) > output.txt
move /Y output.txt source.txt
In this code the target line is found in one operation via a findstr regex that search for the desired acct no. in the third comma-separated field of the line. The rest of the program is simple enough to be self-explanatory...
If you have any doubt of any command, you may review its help executing it with /? parameter; for example: findstr /?
Here is a possible way of doing what you want -- for integer values only (consult the explanatory remarks rem in the code):
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_FILE=.\data.csv" & rem // (path to CSV file to modify)
set "_TMPF=%TEMP%\%_FILE%.tmp" & rem // (path to temporary file)
set "_ACCT=%~1" & rem // (account number to search, taken from first argument)
rem // Write modified CSV data to temporary file:
> "%_TMPF%" (
rem // Reset flag to indicate header (first row):
set "SKIP="
rem // Read CSV file line by line and extract seven tokens (columns):
for /F "tokens= 1-7 delims=, eol=," %%A in ('type "%_FILE%"') do (
rem // Check whether line is header, skip it from modification in case:
if defined SKIP (
rem // Check whether current account number matches:
if /I "%%C"=="%_ACCT%" (
rem // Assemble first three call values (do not modify):
set "PREF=%%A,%%B,%%C"
rem /* Invert sign of remaining four (numeric) cell values;
rem instead, you could also simply write this:
rem `echo(%%A,%%B,%%C,-%%D,-%%E,-%%F,-%%G`, but this
rem would lead to `--` if a number is already negative: */
set /A "VAL1=-%%D, VAL2=-%%E, VAL3=-%%F, VAL4=-%%G"
rem // Return modified line:
setlocal EnableDelayedExpansion
echo(!PREF!,!VAL1!,!VAL2!,!VAL3!,!VAL4!
endlocal
) else (
rem // Account number does not match, so return original line:
echo(%%A,%%B,%%C,%%D,%%E,%%F,%%G
)
) else (
rem // Line is the header, so return original line:
echo(%%A,%%B,%%C,%%D,%%E,%%F,%%G
rem // Next line is certainly not a header:
set "SKIP=#"
)
)
)
rem // Replace original CSV file with temporary file:
> nul move /Y "%_TMPF%" "%_FILE%"
endlocal
exit /B
Here is another way -- for decimal values, which are actually treated as strings (see remarks rem):
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_FILE=.\data-dec.csv" & rem // (path to CSV file to modify)
set "_TMPF=%TEMP%\%_FILE%.tmp" & rem // (path to temporary file)
set "_ACCT=%~1" & rem // (account number to search, taken from first argument)
rem // Write modified CSV data to temporary file:
> "%_TMPF%" (
rem // Reset flag to indicate header (first row):
set "SKIP="
rem // Read CSV file line by line and extract seven tokens (columns):
for /F "tokens= 1-7 delims=, eol=," %%A in ('type "%_FILE%"') do (
rem // Check whether line is header, skip it from modification in case:
if defined SKIP (
rem // Check whether current account number matches:
if /I "%%C"=="%_ACCT%" (
rem // Assemble first three call values (do not modify):
set "PREF=%%A,%%B,%%C"
rem // Invert sign of remaining four (numeric) cell values:
set "VAL1=-%%D" & set "VAL2=-%%E" & set "VAL3=-%%F" & set "VAL4=-%%G"
rem // Return modified line, avoiding doubled minus-signs:
setlocal EnableDelayedExpansion
echo(!PREF!,!VAL1:--=!,!VAL2:--=!,!VAL3:--=!,!VAL4:--=!
endlocal
) else (
rem // Account number does not match, so return original line:
echo(%%A,%%B,%%C,%%D,%%E,%%F,%%G
)
) else (
rem // Line is the header, so return original line:
echo(%%A,%%B,%%C,%%D,%%E,%%F,%%G
rem // Next line is certainly not a header:
set "SKIP=#"
)
)
)
rem // Replace original CSV file with temporary file:
> nul move /Y "%_TMPF%" "%_FILE%"
endlocal
exit /B
Note: The powershell tag was only added to the question much later, so this answer should be considered out of competition.
PowerShell enables a concise and robust solution:
$acctNo = 3456
Import-Csv in.csv | ForEach-Object {
if ($_.'acct no.' -eq $acctNo) {
foreach($prop in (Get-Member -InputObject $_ data*)) {
$_.$($prop.name) = '-' + $_.$($prop.name)
}
}
$_
} # add, e.g., | Out-File -Encoding utf8 out.csv to save to a (different) file.
Import-Csv file reads the input CSV file and converts each row into a custom object whose properties correspond to the column values of each row.
The ForEach-Object cmdlet processes each such object:
Automatic variable $_ represents the input object at hand in each iteration.
if ($_.'acct no.' -eq $acctNo) checks for the account number of interest.
Get-Member -InputObject $_ data* uses reflection to return all properties on the input object whose name starts with data.
foreach(...) processes all matching properties in a loop.
$_.$($prop.name) = '-' + $_.$($prop.name) updates each matching property by prepending - to the existing value.
Note that you can't save the results directly back to the same file - unless you use (Import-Csv in.csv) instead of just Import-Csv in.csv, but that means that the entire input file will be read into memory as a whole.
(
for /f "tokens=1-7delims=," %%a in (yourfilename.txt) do (
if "%%c"=="3456" (echo %%a,%%b,%%c,-%%d,-%%e,-%%f,-%%g
) else (echo %%a,%%b,%%c,%%d,%%e,%%f,%%g)
)
)>processedfilename.txt
should work. Note that the entire for command is enclosed in parentheses to ensure that the output of the echoes is redirected to the processedfile name, which must not be the same as the source data filename.
Naturally, 3456 could be replaced by a variable if desired.
Here's the test batch I used - it is exactly the same as the code I posted, just with the filenames constructed to suit my test system.
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
SET "filename1=%sourcedir%\q43354291.txt"
SET "outfile=%destdir%\outfile.txt"
(
for /f "tokens=1-7delims=," %%a in (%filename1%) do (
if "%%c"=="3456" (echo %%a,%%b,%%c,-%%d,-%%e,-%%f,-%%g
) else (echo %%a,%%b,%%c,%%d,%%e,%%f,%%g)
)
)>"%outfile%"
GOTO :EOF
Here's the input file I used - it's simply your data with a couple of lines duplicated and fixed to suit account=3456
Organization, month,acct no.,data1,data2,data3,data4
orgA,Jan,1234,78900,78900,78900,78900
orgA,Jan,3456,78900,78900,78900,78900
orgA,Jan,6789,78900,78900,78900,78900
and here's the output file
Organization, month,acct no.,data1,data2,data3,data4
orgA,Jan,1234,78900,78900,78900,78900
orgA,Jan,3456,-78900,-78900,-78900,-78900
orgA,Jan,6789,78900,78900,78900,78900
which appears to be what you require.

Batch command - adding date at the end of folder

I currently run a batch command to create a folder 1 day in advanced and label it as MMDDYY.
Everything is working as intended except single digit days. Currently it named the next day folder has 12214, is it possible to have it name it as 120214?
#echo off
for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "dt=%%a"
set "YY=%dt:~2,2%"
set "YYYY=%dt:~0,4%"
set "MM=%dt:~4,2%"
set "DD=%dt:~6,2%"
set "HH=%dt:~8,2%"
set "Min=%dt:~10,2%"
set "Sec=%dt:~12,2%"
:loop
set /a DD+=1
if %DD% gtr 31 (
set DD=1
set /a MM+=1
if %MM% gtr 12 (
set MM=1
set /a YY+=1
set /a YYYY+=1
)
)
xcopy /d:%MM%-%DD%-%YYYY% /l . .. >nul 2>&1 || goto loop
echo %DD%/%MM%/%YYYY%
mkdir "C:\Users\Name\Desktop\%mm%%dd%%yy%\"
pause
You need to pad again the data once the operations have been done. Also you will need some more logic to handle the month change
#echo off
setlocal enableextensions disabledelayedexpansion
rem Retrieve data
for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "dt=%%a"
set "YY=%dt:~2,2%"
set "YYYY=%dt:~0,4%"
set "MM=%dt:~4,2%"
set "DD=%dt:~6,2%"
set "HH=%dt:~8,2%"
set "Min=%dt:~10,2%"
set "Sec=%dt:~12,2%"
rem Remove padding from date elements and increase day
set /a "y=%YYYY%", "m=100%MM% %% 100", "d=(100%DD% %% 100)+1"
rem Calculate month length
set /a "ml=30+((m+m/8) %% 2)" & if %m% equ 2 set /a "ml=ml-2+(3-y %% 4)/3-(99-y %% 100)/99+(399-y %% 400)/399"
rem Adjust day / month / year for tomorrow date
if %d% gtr %ml% set /a "d=1", "m=(m %% 12)+1", "y+=(%m%/12)"
rem Pad date elements and translate again to original variables
set /a "m+=100", "d+=100"
set "YYYY=%y%"
set "YY=%y:~-2%"
set "MM=%m:~-2%"
set "DD=%d:~-2%"
echo Tomorrow: %YYYY% / %MM% / %DD%
Just add the folder creation in the required format
Batch is cumbersome with date math. Leap years, month / year changes / etc can be a pain to deal with. I suggest using a JScript Date() object, where all such conversions are handled automatically.
As follows is a batch / JScript hybrid script. Save it with a .bat extension and run it as you are used to running your typical batch scripts.
#if (#a==#b) #end /* JScript ignores this multiline comment
:: batch portion
#echo off
setlocal
for /f "tokens=1-3" %%I in ('cscript /nologo /e:JScript "%~f0"') do (
set "MM=%%I"
set "DD=%%J"
set "YYYY=%%K"
)
xcopy /d:%MM%-%DD%-%YYYY% /l . .. >nul 2>&1 || goto loop
echo %MM%/%DD%/%YYYY%
mkdir "%userprofile%\Desktop\%MM%%DD%%YYYY:~-2%\"
pause
goto :EOF
:: end batch portion / begin JScript */
function zeroPad(what) { return (what+'').length < 2 ? '0'+what : what; }
var tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
WSH.Echo([
zeroPad(tomorrow.getMonth() + 1),
zeroPad(tomorrow.getDate()),
tomorrow.getFullYear()
].join(' '));

Calculate business days using a batch file

I have a very simple batch file I am trying to write.
If today is 03/13, I would like my batch file to output:
"I will call you back on 03/15"
So it will take the date and ADD 2 business days. So if it were 03/15:
"I will call you back on 03/19"
Eh, do not worry, it can be done in batch. :) Here is an implementation of mine (~150 lines of code).
Example
https://gist.github.com/DavidRuhmann/4666270
Usage
Do something like this to adjust for the weekends.
if "%Date:~0,3%"=="Thu" call :DaysAhead 4
if "%Date:~0,3%"=="Fri" call :DaysAhead 4
if "%Date:~0,3%"=="Sat" call :DaysAhead 3
if "%Date:~0,3%"=="Sun" call :DaysAhead 2
if "%Date:~0,3%"=="Mon" call :DaysAhead 2
if "%Date:~0,3%"=="Tue" call :DaysAhead 2
if "%Date:~0,3%"=="Wed" call :DaysAhead 2
Use JScript to calculate the date and you're golden.
#if (#X)==(#Y) #end /* (batch + jscript hybrid script init)
:: *** Batch script *****
#echo off
setlocal
for /f %%I in ('cscript /nologo /e:jscript "%~f0"') do (
echo I will call you back on %%I
)
goto :EOF
:: *** JScript script *****/
var dow = new Date().getDay();
var days = (dow > 4) ? 9 - dow : (dow == 4 ? 4 : 2);
var d = new Date(new Date().getTime() + (1000 * 60 * 60 * 24) * days);
WScript.echo((d.getMonth() + 1) + '/' + d.getDate());
If today is Thursday, the script will return the following Monday. Friday through Sunday, the following Tuesday. Monday through Wednesday, two days ahead. And you don't have to worry about locale, leap year, leap frogs, lunar cycles, etc.
The Batch file below do what you want:
#echo off
rem AddBusinessDays.bat date numOfDays
rem Antonio Perez Ayala
rem Convert the date to Julian Day Number + number of days
for /F "tokens=1-3 delims=/" %%a in ("%1") do (
set /A mm=10%%a %% 100, dd=10%%b %% 100, yy=%%c
)
set /A a=mm-14, jd=(1461*(yy+4800+a/12))/4+(367*(mm-2-12*(a/12)))/12-(3*((yy+4900+a/12)/100))/4+dd-32075+2+%2, dow=jd%%7
rem Adjust Julian Day Number to avoid weekends
if %dow% lss 2 set /A jd+=2-dow
rem Convert Julian Day Number back to date
set /A l=jd+68569-2,n=(4*l)/146097,l=l-(146097*n+3)/4,i=(4000*(l+1))/1461001,l=l-(1461*i)/4+31,j=(80*l)/2447,dd=l-(2447*j)/80,l=j/11,mm=j+2-(12*l),yy=100*(n-49)+i+l
rem Assemble the result
if %dd% lss 10 set dd=0%dd%
if %mm% lss 10 set mm=0%mm%
set newDate=%mm%/%dd%/%yy%
echo %newDate%
Reference: http://www.hermetic.ch/cal_stud/jdn.htm#comp
For example:
>echo %date%
03/13/2013
>AddBusinessDays.bat %date% 2
03/15/2013
>AddBusinessDays.bat %date% 3
03/18/2013
>AddBusinessDays.bat %date% 4
03/18/2013
>AddBusinessDays.bat %date% 5
03/18/2013
>AddBusinessDays.bat %date% 6
03/19/2013
Antonio
PS - Yes, I know that this method will not work for everyone in the world. The good news are that I not wrote this solution for they all, but precisely for the OP although it is very easy to modify it for every computer. For example, previous program does NOT work in my computer because my locale is DD/MM/YYYY, but I can interchange dd and mm in two lines of previous program and I am pretty sure that most people in this world are also capable to do so! ;-)
Hi Antonio,
Just today I found that the code you shared didn't work for more than 7 days ahead, I changed some thing and now it works ever.
#echo off
rem AddBusinessDays.bat date numOfDays
rem adapted by Leonardo Contreras based on Antonio Perez Ayala with handling for more than 7 days
rem to convert Dow mm/dd/yyyy to mm/dd/yy
set mydate=%date:~4,2%/%date:~7,2%/%date:~10,4%
rem Convert the date to Julian Day Number + number of days
for /F "tokens=1-3 delims=/" %%a in ("%mydate%") do (
set /A mm=10%%a %% 100, dd=10%%b %% 100, yy=%%c
)
rem dow_orig is based on a 0-6 days statrting on Monday
set /A a=mm-14, jd_orig = (1461*(yy+4800+a/12))/4+(367*(mm-2-12*(a/12)))/12-(3*((yy+4900+a/12)/100))/4+dd-32075, dow_orig=jd_orig%%7
rem calculate new julian's day
set /A numw = (dow_orig+%3)/5, njd = jd_orig+%3+numw*2, dow=(njd)%%7
rem Adjust Julian Day Number to avoid weekends
if %dow% gtr 5 (set /A jd+=2 )
rem Convert Julian Day Number back to date
set /A l=njd+68569,n=(4*l)/146097,l=l-(146097*n+3)/4,i=(4000*(l+1))/1461001,l=l-(1461*i)/4+31,j=(80*l)/2447,dd=l-(2447*j)/80,l=j/11,mm=j+2-(12*l),yy=100*(n-49)+i+l
rem Assemble the result
if %dd% lss 10 set dd=0%dd%
if %mm% lss 10 set mm=0%mm%
set newDate=%mm%/%dd%/%yy%
echo %newDate%