Dr.Prog
Dr.Prog

Reputation: 243

How can I use a batch script to remove folder and all of its contents based on folder name in YYYYMMDD format?

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

Answers (4)

user6811411
user6811411

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

Compo
Compo

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

ienaxxx
ienaxxx

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

Magoo
Magoo

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

Related Questions