我目前使用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天。
我怎样才能做到这一点?
答案 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