Add 1 year to the current date in a batch file - batch-file

Hi couldnt find anything here to help out with this one.
My company has a set of client folders that require a set of subfolders to be created at the end of each financial year. This is required to be a 2 digit representation of the year (ie - 14 Folder1 [for 2014] and so on).
I have a batch file that creates the folders every year, but have to modify the year every time. I am looking to schedule an auto mated solution, but i am stuck trying to add 1 additional year to the date. (as the folders need to be created at the end of the financial year, not calender year).
I am looking for a way to add 1 year to the current date. Here is my batch file so far. Any ideas anyone?
set YEAR= %DATE:~-2% + %DATE:~-2%
for /f "delims=|" %%s in ('dir /ad/b') do md "%%s\%YEAR% Folder1"
for /f "delims=|" %%s in ('dir /ad/b') do md "%%s\%YEAR% Folder2"
for /f "delims=|" %%s in ('dir /ad/b') do md "%%s\%YEAR% Folder3"

Like this :
set /a YEAR=%DATE:~-2% + 1

set /a YEAR=1%DATE:~-2%+1
set YEAR= %DATE:~-2%%YEAR:~-2%
This is assuming that you want 1415 for the 2014-2015 financial year.
Are you aware that your construct will yield a Space before the string? Spaces are significant in string-assignments - on both sides of the =.
It's safer to use
set "YEAR=%DATE:~-2%%YEAR:~-2%"
for instance - the rabbit's ears in this format ensure that trailing spaces are omitted (that can cause chaos)

Related

Checking if there already is a sub-folder bearing date in its name before attempting to create a newer version of it - using BAT script

So I got my answer to the
How to create a folder with current date in its name and copy to it all files and folders from some path on Windows 10
question, but as it was a duplicated issue and I am a newbie on this forum- it was closed and I am unable to ask additional question in similar topics
By using this How to create a subfolder based on current date? solution I was able to achieve what I wanted [thank you very much user compo]
And so this code is working A-OK:
#Echo Off
Set "sd=C:\Users\YOUR USER NAME\AppData\Roaming\Mozilla\Firefox\Profiles\fsj89244"
Set "dd=D:\Backup Copies\Firefox\Profile"
Set "ds="
If Not Exist "%sd%\" Exit /B
For /F "Tokens=1-3Delims=/ " %%A In ('RoboCopy/NJH /L "\|" Null'
) Do If Not Defined ds Set "ds=%%A %%B %%C"
If Not Defined ds Exit /B
RoboCopy "%sd%" "%dd%\%ds%" /E
It creates a sub-folder with a date [on drive D] in its name and then copies to it all content from a specified path [from the drive C]. This speeds up my manual creation of backup copies
But if the script is executed again I would need it to check first if such sub-folder exists. And if yes then leave it alone and create a folder with name in date format >>YYYY MM DD v2<<; and the next time >>YYYY MM DD v3<< etc. which would stop happening when the date in the operating system would change to a next day
Set "ds="
For /F "Tokens=1-3Delims=/ " %%A In ('RoboCopy/NJH /L "\|" Null'
) Do If Not Defined ds Set "ds=%%A %%B %%C"
If Not Defined ds Exit /B
set ver=0
for /f "tokens=3,4 delims=v " %%a in ('dir /ad /on /b "%ds%*"') do set /a ver=%%b+1
set "newFolder=%ds% v%ver%"
md "%newFolder: v0=%"
dir /ad /on will sort the folders by name and the for ends with the last version plus one (The obvious for /d %%a in ("%ds%*") do set /a ver+=1 just counts the found folders and so will be incorrect if a folder is missing for any reason and probably will use an already "occupied" folder)
The first folder of a day will be in the format YYYY MM DD, all further folders will be in the format YYYY MM DD vX. If you want the first folder to be the same format (... v0), use just md "%newFolder%.

robocopy command to move file based on created date

I have files in a folder 'FILEPATH', each file has different created date and modified date(modified date is less than created date).
I want to delete the files with created date greater than 10days. I used below command but it works on modified date.
ROBOCOPY %FILEPATH% %DUMPFOLDER% /move /minage:10
del %DUMPFOLDER% /q
On some forums its written that minage refers to created date but it's referring to modified date while executing. Am I doing something wrong here? Or is there any other alternate.
Unfortunately, there's no easy way to do this. The only commands of which I'm aware that can deal with file creation dates are dir /t:c and wmic datafile. There could be others, but there are none that simplify performing date math as forfiles or robocopy do.
Since date math in batch is cumbersome anyway, in this situation it makes sense to borrow from another runtime environment -- PowerShell, for example, or VBScript or JScript. The Windows Scripting Host FileSystemObject's File Object has properties for DateCreated, DateLastAccessed, and DateModified. With JScript, getting a file's age based on its DateCreated property is simply a matter of JavaScript Date() arithmetic.
Here, salt this .bat script to taste:
#if (#CodeSection == #Batch) #then
#echo off
setlocal
set "FILEPATH=c:\path\to\whatever"
set "age=10"
for %%I in ("%FILEPATH%\*") do (
call :getAge result "%%~fI"
setlocal enabledelayedexpansion
if !result! gtr %age% (
echo %%~nxI created !result! days ago and should be deleted
rem del "%%~fI"
) else (
echo %%~nxI is new ^(created !result! days ago^)
)
endlocal
)
goto :EOF
:getAge <return_var> <filename>
for /f "delims=" %%I in ('cscript /nologo /e:Jscript "%~f0" "%~2"') do set "%~1=%%I"
goto :EOF
#end
// JScript portion
var fso = WSH.CreateObject('scripting.filesystemobject'),
created = fso.GetFile(WSH.Arguments(0)).DateCreated,
age = new Date() - created;
WSH.Echo(Math.floor(age / 1000 / 60 / 60 / 24));
If you want something simpler, you could employ wmic datafile and get the first 8 digits of get creationdate like this cat does, but his solution doesn't take into account time of day. Such a method might inappropriately delete files that are 9 days, 23 hours old. Then there's also the problem of calculating days across new months. The JScript method above tests file age based on the current moment, rather than based on midnight; and will handle spanning months, years, and leap years with no conscious effort.

Get date from file name and check age

I will have a variable that will be equal to anything from 1-7, which will represent 1 day old and so on. I need to find a file that is the same age in days as that variable.
For example
set "age=4"
// code to find the file OR folder that is 4 days old
It's worth noting that I need to get the filename of this file
Here, try this:
#echo off
setlocal
set age=4
set /a maxage=age+1
:: For files that are %age% days old or older, set a variable
for /f "delims=" %%I in ('forfiles /d -%age%') do (
set "fileArr[%%~snxI]=%%~fI"
)
:: for files that are %age% + 1 days old or older, unset variable
for /f "delims=" %%I in ('forfiles /d -%maxage%') do (
set "fileArr[%%~snxI]="
)
:: Get values of all remaining fileArr variables
for /f "tokens=1,* delims==" %%I in ('set fileArr') do echo(%%J
As you can see from the comments, first the script gets all files %age% days old or older, and sets a variable. To make the variable name unique and to be able to index it later, the variable name contains the short filename, simulating an associative array. Next, it unsets those variables which are %age% + 1 days old or older, then outputs what's left.
No painful date math is needed. forfiles handles the computation. If you needed age-by-minutes computation, admittedly that gets a little more complicated; but forfiles handles math by day just fine.
I found a much easier soloution:
ROBOCOPY "D:\file-backups\%ThisUser_Username%\Server"^
"%ThisService_WorkingDirectory%#DayZ_Epoch_Server\Addons"^
"dayz_server_*.pbo"^
/minage:%ThisService_filerestoreage%^
/maxage:%ThisService_filerestoreage%
In batch, as soon as you get the date of modification which corresponds to the age, (thus %DATE% - %AGE%), you can use the ~t modifier in a parameter expansion to get the age of the file.
Note that if you have PowerShell on your system (and you really should because it's preinstalled since Win7, cf comments) you can use it to do the date calculation easily.
Hence, a script that does what you want (with the parameter being %age% which you can replace with a command-line parameter for example) :
set age=4
for /f "delims=|" %%i in ('powershell.exe -Command "Get-Date -Format dd/MM/yyyy -Date ([DateTime]::Today.AddDays(-%age%))"') do set age_date=%%i
echo Files modified %age% days ago (the %age_date%) are :
setlocal ENABLEDELAYEDEXPANSION
for /f "delims=|" %%f in ('dir /b') do (
set file_date=%%~tf
if "!file_date:~0,10!"=="%age_date%" (echo %%f)
)
For a pure-batch script to get the date to replace the powershell call (say for legacy versions), you could slightly modifiy the code from here : http://www.powercram.com/2010/07/get-yesterdays-date-in-ms-dos-batch.html , even though that would get very ugly.
In contrast, unix-like systems have a tool for this, see man find, which is more user-friendly.
find /path/to/parent/directory -daystart -atime $age
atime : File was last accessed n*24 hours ago
$age without leading + or - : find exactly age of $age*24 hours (as opposed to less or equal, or superior or equal)
daystart :
Measure times (for -amin, -atime, -cmin, -ctime, -mmin, and
-mtime) from the beginning of today rather than from 24 hours
ago
You can use mtime instead of atime for modified date instead of creation date.

list with all dirs + date of file with oldest last modified date

been doing research all day and I probably could have done this manually but I just want to learn how to do it to expand my knowledge
REQUIREMENTS:
I have a folder with 11xxx subfolders, I need to know when the oldest file within each of these subfolders was last modified
so far I tried to use the dir command to get a list of all folders and the last modified date of each of the files within a folder
echo Starting...
#echo off
if exist files.txt (del files.txt)
dir /on /s /tw /a-d | find /v "<DIR> ." | find /v "File(s)" > files.txt
if exist files1.txt (del files1.txt)
For /F "delims=" %%A in (files.txt) Do Echo %%A >> files1.txt
if exist files2.txt (del files2.txt)
For /F "skip=2 delims=*" %%A in (files1.txt) Do Echo %%A >> files2.txt
#echo on
echo Finishing...
del files.txt
del files1.txt
ren files2.txt files.txt
quit
ok so the above gave me a txt file in this format
Directory of C:\TEMP
2013/12/05 05:30 PM 22,528 6N85.mst
2011/06/21 12:01 PM 14,108,096 CitrixOnlinePluginWeb.exe
2014/02/19 01:59 PM 448 extract.cmd
2014/02/19 03:42 PM 0 files.txt
2011/08/04 08:41 AM 216 GLF1C8.tmp
2011/08/04 08:41 AM 2,630 GLF1C9.tmp
2011/08/04 08:41 AM 54 GLF1CA.tmp
2011/08/04 08:41 AM 64 GLF1CB.tmp
2011/07/05 12:29 PM 239,174 ITMURebootMSG.EXE
2013/11/28 04:20 PM 2,434,048 msxml.msi
2013/11/28 12:59 PM 2,066,376 msxml4-KB2758694-enu.exe
2004/04/15 10:10 AM 79 process.bat
2012/08/02 12:43 AM 4,594 process.log
2003/11/04 10:17 AM 376 procs.vbs
2014/02/18 03:32 AM 16,391 WakeUpAgt.LO_
2014/02/19 12:04 PM 9,247 WakeUpAgt.LOG
2005/03/09 09:40 AM 4,630,256 WindowsXP-KB895200-x86-ENU.exe
2005/10/12 02:06 PM 4,934,896 WINDOWSXP-KB902400-X86-ENU.exe
2006/05/25 12:12 PM 1,307,376 WindowsXP-KB913580-x86-ENU.exe
Total Files Listed:
0 Dir(s) 81,741,336,576 bytes free
I opened the txt file within excel to get the first 10 chars of each line to get the date in col A,
IMO this approach is wrong, maybe I should be doing it in a different way, anyone care to help?
You're on the right track. The built-in dir command, as you found, can do your sorting for you. If you only care about the date of the oldest file, let it sort by date modified (descending) and get the last entry in the list. This should do what you're after, I think:
for /f %%x in ('dir /b /o-d /a-d') do set OLDESTFILE=%%~fx last modified at %%~tx
echo %OLDESTFILE%
Let me break this down.
The switches to the dir command will give you a list of files only (/a-d), in "brief" form (/b - just a list of files, not the typical full dir output), and will sort that list by date, descending (/o-d).
The for loop that wraps around that iterates over each of these files and sets an environment variable to the text in the format:
C:\TEMP\WindowsXP-KB913580-x86-END.exe last modified at 2006/05/25 12:12 PM
You can read for /? for all of the gritty details about the other ~ modifiers you can use.
If you run this with echo on, you'll see that it actually sets this environment variable each time through the loop, overwriting it with each subsequent iteration. That's ok by us, though, since we only really want the last entry anyway.
Now, if you really only want the date and not the time, that's slightly trickier. You'll need to use a slightly uglier loop like this:
for /f %%x in ('dir /b /o-d /a-d') do (
for /f "tokens=1" %%a in ("%%~tx") do (
set OLDESTFILE=%%~fx last modified on %%a
)
)
echo %OLDESTFILE%
The inner for loop here takes the date and time (e.g., 2006/05/24 12:12) as a list of arguments. Since cmd uses spaces as delimiters by default, this gives you two tokens, 2006/05/24 and 12:12. By specifying tokens=1 you explicitly tell for that you only care about the first of those: the date*.
Hope this gets you going on the right track. Now that you have the tricky part, you can wrap all of this in a loop that gets you the list of directories you care to run this in.
*Pedantically speaking, you don't actually need the tokens=1 there, since %%a would only refer to the first token anyway, and the time would be in %%b, but I thought it would be useful for illustrative purposes.
first of all, thank you #Mark for helping me understand the for loops in dos, I was having trouble with them yesterday and I just couldn't figure out how they worked but now I think I understand!
one of the problems I found with %%~tx was that it didn't extract the last modified date, only the last accessed date, maybe I'm wrong but I figured I'd try a different approach anwyay
::delete any files called list.txt if they exist
if exist list.txt (del list.txt)
::loop through all directories including sub-directories
for /d /r %%x in (*) do (
if exist listTemp1.txt (del listTemp1.txt)
::loop through each file within directory, show time last written, sort desc
for /f "delims=" %%y in ('dir "%%x" /tw /o-d') do (
::append listTemp1.txt with list of files
echo %%y >> listTemp1.txt
)
if exist listTemp2.txt (del listTemp2.txt)
::append listTemp2.txt with lines containing / in the dates
find "/" listTemp1.txt >> listTemp2.txt
::loop through listTemp2.txt to get last line of file, no delims as the first space is after date and we only need date, set var OLDFile with date and current folder
for /f %%z in (listTemp2.txt) do set OLDFile=%%z %%x
::append list.txt with OLDFile
call echo %%OLDFile%% >> list.txt
)
if exist listTemp1.txt (del listTemp1.txt)
if exist listTemp2.txt (del listTemp2.txt)
the above script gave me the exact result I wanted, which was <date of oldest file within folder> <folder>
2014/02/20 C:\TEMP\folder 1
2014/02/19 C:\TEMP\folder 2
2014/02/19 C:\TEMP\folder 1\folder 2
I created temporary txt files since I couldn't pipe for loop results (possible?)
anyways, thanks again #Mark, couldn't have figured out how to do this without your help examples and most importantly the break down which helped me understand the code!

.bat file to change a file name to 1 day less than current date [duplicate]

This question already has answers here:
How can I create a date stamp for yesterday
(2 answers)
Closed 8 years ago.
I am a novice at writing scripts but I know this can be done I just don't know how...
I have a file that need to have the file NAME changed to the current date less 1 workday (ex: Mondays date back Friday, Tuesdays to Monday with a prepend of the date a static "AD"
Filename example: AD140107.pos
(Tuesdays date changed to a Wednesday date, AD140108.pos)
The file is located at: R:\PortfolioCenter\Output\Manual Interface Files
I have a similar file in a different folder that has a different date format that needs the date changed as well
Filename example: PC010714.slb
(Tuesdays date changed to a Wednesday date, PC010814.pos)
This file is located at: R:\slwin\Recon adjustments
I would like both file names to change using the same script
I know DOS doesn't do weekdays well so I can use a separate file to process Monday files if neccesary
#ECHO OFF
SETLOCAL
SET "destdir=c:\destdir"
SET "targetdir=c:\destdir"
SET today=%date:~-2%%date:~3,2%%date:~0,2%
FOR /f "delims=" %%a IN (yesterday.txt) DO SET yesterday=%%a
IF %yesterday%==%today% GOTO :EOF
>yesterday.txt ECHO %today%
ECHO REN "%destdir%\AD%today%.pos" "AD%yesterday%.pos"
SET today=%today:~-4%%today:~0,2%
SET yesterday=%yesterday:~-4%%yesterday:~0,2%
ECHO REN "%targetdir%\PC%today%.slb" "PC%yesterday%.slb"
GOTO :EOF
I use a date format of dd/mm/yyyy. Yours may be different, so you'd need to reformat the date differently. The basic method is to string together the three elements using substrings of the form %date:startpos,length% where position 0 is the start of the (date) string.
I've nominaed the two directories as destdir and targetdir to suit my system.
There's some confusion in the question about what name gets changed to what. It would seem more sensible to change from the current date to the previous day's date, but that's not what the narrative describes.
I'm assuming that you are only going to run this once per day.
It's all based around keeping the massaged last-run date in yesterday.txt, which would need to be established first containing a single line140107` or whatever. If you have this run automagically at midnight+alittle, Mon-Fri only, it should rename the files appropriately.
The required commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO REN to REN to actually rename the files.
The Batch subroutine below get the midweek date of current date minus one day and show it in the format given by its parameter: if it is Y, output format is YYMMDD, otherwise it is MMDDYY. This routine solve the main part of your request.
#echo off
setlocal
rem If Format=Y, output is YYMMDD
rem If Format=M, output is MMDDYY
:OneMidweekDayLessCurrentDate format
rem Modify next line accordingly to your locale format (this one use DD/MM/YYYY)
for /F "tokens=1-3 delims=/" %%a in ("%date%") do set /A dd=1%%a-100, mm=1%%b-100, yyyy=%%c
rem Convert the Date minus one day to Julian Day Number, and get its Day Of Week (0=Sunday, ..., 6=Saturday)
set /A a=(mm-14)/12, jdn=(1461*(yyyy+4800+a))/4+(367*(mm-2-12*a))/12-(3*((yyyy+4900+a)/100))/4+dd-32076, dow=jdn%%7
rem If the dow is Sunday or Saturday, change it by the previous Monday
if %dow% equ 0 (
set /A jdn-=2
) else if %dow% equ 6 (
set /A jdn-=1
)
rem Convert the Julian Day Number back to date
set /A l=jdn+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
set /A dd=l-(2447*j)/80,l=j/11,mm=j+2-(12*l),yyyy=100*(n-49)+i+l
if %dd% lss 10 set dd=0%dd%
if %mm% lss 10 set mm=0%mm%
rem Show the resulting date
if "%1" equ "Y" (
echo %yyyy:~-2%%mm%%dd%
) else (
echo %mm%%dd%%yyyy:~-2%
)
exit /B
On the other hand you have NOT specified which file is the one to be renamed: "I have a file that need to have the file NAME changed... Filename example: AD140107.pos". If you specify this point, we can complete the solution.

Resources