【问题标题】:How can I use a batch script to remove folder and all of its contents based on folder name in YYYYMMDD format?如何使用批处理脚本根据 YYYYMMDD 格式的文件夹名称删除文件夹及其所有内容?
【发布时间】:2018-09-16 14:18:25
【问题描述】:

我目前使用 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 天。

我怎样才能做到这一点?

【问题讨论】:

  • 这在 PowerShell 中要容易得多。我建议切换。

标签: batch-file robocopy


【解决方案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 脚本并不是为实际删除目录而设计的,只是向您展示将要删除的内容。要真正删除它们,请从 6 行中删除 -WhatIf

【讨论】:

  • 感谢 powershell 提示!是否可以创建通过 powershell 删除的文件夹的日志?
  • Remove-Item 不会产生任何输出,通常的方法是使用Test-Path 并稍后检查它是否存在。另一种方法是将-WhatIf 输出到您的日志文件,然后在没有该选项的情况下运行Remove-Item。您甚至可以在删除之前将名称输出到日志中。 我将把它留给你,让你自己研究和决定,因为迟到的请求在技术上超出了你最初问题的范围
【解决方案2】:
for /f "skip=%max_days%" %%d in ('dir /b /ad /o-n "%dump_path%\20*" ') do ECHO rd /s /q "%dump_path%\%%d"

将是我的选择。

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

for /f 处理dir 结果时,第一行max_days 将被跳过,因此剩下31 代。

这避免了批量非常复杂的日期计算,但留下了 31 代,无论月份长短以及任何可能因假期等原因被跳过的日子。

【讨论】:

  • 这里假设OP每天都在备份,有些人放假,所以不符合规定的要求! 我接受它不会删除不应该删除的内容,但可能会留下本应删除的内容
  • @Compo:是的,但如果 OP 在巡航中离开,那么字面上的“31 天”可能会删除太多 许多 备份。这完全取决于对时间的解释的字面意思。
【解决方案3】:

恕我直言,最简单的解决方案是不要让批次在日期上做算术(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
)

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

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

这种方式的优点是即使您的备份脚本中断并停止备份,也可以保留最新的 31 个目录。即使没有新的备份来替换它们,您也可以删除最旧的副本。

希望对你有帮助

【讨论】:

  • 这里假设OP每天都在备份,有些人放假,所以不符合规定的要求! 我接受它不会删除不应该删除的内容,但可能会留下本应删除的内容
  • 你是绝对正确的。虽然,如果 OP 定期备份(比如说每周两次),他可以调整删除批次的时间表和 MORE 命令后的“+31”,确实得到预期的结果。
【解决方案4】:

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

@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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-23
    • 1970-01-01
    • 2018-07-22
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多