Reputation: 243
I currently use a robocopy batch script to make backup copies of directories, the batch script below creates a folder in the format YYYYMMDD of the current date the script is ran.
Script Below:
@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%"
set "datestamp=%YYYY%%MM%%DD%"
robocopy "\\fsfiles\d$" "D:\Backups\Inc\%datestamp%" /S /W:0 /R:1 /MAXAGE:1 /A-:SH
I then use another batch script to remove the backups after 31 days.
Script Below:
@echo off
:: set folder path
set dump_path=D:\Backups\Inc
:: set min age of files and folders to delete
set max_days=31
:: remove files from %dump_path%
forfiles -p %dump_path% -m *.* -d -%max_days% -c "cmd /c del /q @path"
:: remove sub directories from %dump_path%
forfiles -p %dump_path% -d -%max_days% -c "cmd /c IF @isdir == TRUE rd /S /Q @path
While the script to remove the folder and all of its contents based on the date the folder was created works, I would like to change it to remove the folder and all of its contents based on the folder name in date format YYYYMMDD if it's older than 31 days.
How can I achieve this?
Upvotes: 0
Views: 708
Reputation:
Since your date format is sortable and comparable I'd use:
@echo off
:: set folder path
set dump_path=D:\Backups\Inc
PushD "%dump_path%"
:: set min age of files and folders to delete
set max_days=31
:: Use PowerShell to eval max_days
for /f %%A in (
'powershell -NoP -Noni -C "(Get-Date).AddDays(-%max_days%).ToString(\"yyyyMMdd\")"'
) Do set PurgeDate=%%A
For /F "tokens=*" %%A in ('Dir /B /ON "20*" '
) Do If "%%A" Gtr "20000101" if "%%A" Lss "%PurgeDate%" Echo RD /S /Q "%%A"
PopD
Upvotes: 0
Reputation: 38623
For the initial script, there's nothing wrong with using WMIC
for the date retrieval. However you're using RoboCopy
already, so you can use that to retrieve the date you require:
@Echo Off
For /F "Tokens=1-3 Delims=/ " %%A In ('RoboCopy/NJH /L "\|" Null'
) Do Set "ds=%%A%%B%%C"&GoTo BackUp
Exit /B
:BackUp
RoboCopy "\\fsfiles\D$" "D:\Backups\Inc\%ds%" /S /W:0 /R:1 /MaxAge:1 /A-:SH
For you're second script I'd suggest, as did your first commentor, using PowerShell
instead.
Here's an example .ps1
script which would remove directories with name strings older than 1 month, (most likely the intention):
$MonthAgo = (Get-Date).AddMonths(-1)
$Folders = (Get-ChildItem "D:\Backups\Inc" | Where-Object {$_.PSIsContainer -Eq $True -And $_.Name -Match '^\d{8}'})
ForEach ($f In $Folders) {
$FolderDate = Get-Date -Year $f.Name.SubString(0,4) -Month $f.Name.SubString(4,2) -Day $f.Name.SubString(6,2)
If ($FolderDate -LT $MonthAgo) {
Remove-Item $f.FullName -WhatIf
}
}
…and similarly to remove directories with name strings older than 31 days:
$DaysAgo = (Get-Date).AddDays(-31)
$Folders = (Get-ChildItem "D:\Backups\Inc" | Where-Object {$_.PSIsContainer -Eq $True -And $_.Name -Match '^\d{8}'})
ForEach ($f In $Folders) {
$FolderDate = Get-Date -Year $f.Name.SubString(0,4) -Month $f.Name.SubString(4,2) -Day $f.Name.SubString(6,2)
If ($FolderDate -LT $DaysAgo) {
Remove-Item $f.FullName -WhatIf
}
}
The powershell scripts above, were not designed to actually remove the directories, just show you what would be removed. To actually remove them, delete -WhatIf
from line 6
Upvotes: 1
Reputation: 1300
The simplest solution IMHO is NOT TO ask batch to do arithmetic stuff on dates (Aquila non captat muscas :-) )
Try this simple script instead.
@echo off
Setlocal EnableDelayedExpansion
set dump_path=D:\Backups\Inc
FOR /F "Usebackq" %%a IN (`DIR /AD /B /O-N "!dump_path!" ^| MORE +31`) DO (
echo %%a
)
Obviously i put an "echo" instead of the remove command, to let you evaluate how this works. You can then put the deletion command inside the parenthesis.
Substantially, if you are sure your dir names are in the form of YYYYMMDD, it lists them in reverse order, excluding the first 31.
This way has the advantage of keeping the newest 31 Dirs even if your backup script breaks and stop making backup. The other ways you'd have the oldest copies deleted even if there's no new backup to replace them.
Hope this helps
Upvotes: 0
Reputation: 80023
for /f "skip=%max_days%" %%d in ('dir /b /ad /o-n "%dump_path%\20*" ') do ECHO rd /s /q "%dump_path%\%%d"
would be my choice.
Perform a dir
in /b
(basic) mode, showing /ad
directories only, in /o-n
reverse-name order. Using the 20*
mask "shows" only directorynames that start 20
.
The first max_days
lines are skipped when for /f
processes the dir
result, so 31 generations remain.
This avoids the date-calculation, which is very complex in batch, but leaves 31 generations, regardless of the length of months and any days that might have been skipped due to holidays, etc.
Upvotes: 1