如何使用批处理脚本根据YYYYMMDD格式的文件夹名称删除文件夹及其所有内容?

时间:2018-04-06 14:08:20

标签: batch-file robocopy

我目前使用robocopy批处理脚本制作目录的备份副本,下面的批处理脚本以脚本运行的当前日期的YYYYMMDD格式创建一个文件夹。

下面的脚本:

@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

然后我使用另一个批处理脚本在31天后删除备份。

下面的脚本:

@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 

虽然根据创建文件夹的日期删除文件夹及其所有内容的脚本工作,但我想更改它以根据日期格式YYYYMMDD的文件夹名称删除文件夹及其所有内容它超过31天。

我怎样才能做到这一点?

4 个答案:

答案 0 :(得分:1)

for /f "skip=%max_days%" %%d in ('dir /b /ad /o-n "%dump_path%\20*" ') do ECHO rd /s /q "%dump_path%\%%d"

将是我的选择。

dir(基本)模式下执行/b,仅以/ad反向名称顺序显示/o-n个目录。使用20*掩码“仅显示”以20开头的目录名。

max_days处理for /f结果时,会跳过第一个dir行,因此会保留31代。

这样可以避免日期计算,这个日期计算在批处理上非常复杂,但不管月份的长短和因节假日而可能跳过的任何天数等都会留下31代。

答案 1 :(得分:1)

对于初始脚本,使用WMIC进行日期检索没有任何问题。但是,您已经使用RoboCopy,因此您可以使用它来检索所需的日期:

@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

对于你的第二个脚本我建议和你的第一个评论员一样,改为使用PowerShell

这是一个示例.ps1脚本,它将删除名称字符串超过1个月的目录,(很可能是意图)

$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
    }
}

...同样删除名称字符串超过31天的目录:

$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
    }
}

上面的powershell脚本并不是为了实际删除目录而设计的,只是向您显示要删除的内容。要实际删除它们,请从第-WhatIf

中删除6

答案 2 :(得分:0)

最简单的解决方案恕我直言,不要让批处理在日期做算术(Aquila non captat muscas :-))

请尝试使用这个简单的脚本。

@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
)

显然我放了一个" echo"而不是删除命令,让你评估它是如何工作的。然后,您可以将删除命令放在括号内。

基本上,如果你确定您的目录名称是YYYYMMDD的形式,它会以相反的顺序列出它们,不包括前31个。

即使您的备份脚本中断并停止备份,这种方式也可以保留最新的31 Dirs。您删除最旧副本的其他方式即使没有新备份也可以删除。

希望这有帮助

答案 3 :(得分:0)

由于您的日期格式是可排序的且具有可比性,我会使用:

@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