如何使用批处理脚本根据 YYYYMMDD 格式的文件夹名称删除文件夹及其所有内容?
How can I use a batch script to remove folder and all of its contents based on folder name in YYYYMMDD format?
我目前使用 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
虽然根据文件夹创建日期删除文件夹及其所有内容的脚本有效,但我想更改它以根据日期格式的文件夹名称删除文件夹及其所有内容如果超过 31 天,则为 YYYYMMDD。
我怎样才能做到这一点?
for /f "skip=%max_days%" %%d in ('dir /b /ad /o-n "%dump_path%*" ') do ECHO rd /s /q "%dump_path%\%%d"
将是我的选择。
在 /b
(基本)模式下执行 dir
,仅显示 /ad
目录,顺序为 /o-n
reverse-name。使用 20*
掩码 "shows" 仅以 20
.
开头的目录名
当 for /f
处理 dir
结果时,前 max_days
行被跳过,所以剩下 31 代。
这避免了 date-calculation,它在批处理中非常复杂,但是留下了 31 代,不管月份的长度和任何可能由于假期等原因而被跳过的天数
恕我直言,最简单的解决方案是不要求批处理在日期上做算术运算(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 个目录。即使没有新的备份来替换它们,您也可以通过其他方式删除最旧的副本。
希望这对您有所帮助
对于初始脚本,使用 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
因为你的日期格式是可排序和可比较的,所以我会使用:
@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
我目前使用 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
虽然根据文件夹创建日期删除文件夹及其所有内容的脚本有效,但我想更改它以根据日期格式的文件夹名称删除文件夹及其所有内容如果超过 31 天,则为 YYYYMMDD。
我怎样才能做到这一点?
for /f "skip=%max_days%" %%d in ('dir /b /ad /o-n "%dump_path%*" ') do ECHO rd /s /q "%dump_path%\%%d"
将是我的选择。
在 /b
(基本)模式下执行 dir
,仅显示 /ad
目录,顺序为 /o-n
reverse-name。使用 20*
掩码 "shows" 仅以 20
.
当 for /f
处理 dir
结果时,前 max_days
行被跳过,所以剩下 31 代。
这避免了 date-calculation,它在批处理中非常复杂,但是留下了 31 代,不管月份的长度和任何可能由于假期等原因而被跳过的天数
恕我直言,最简单的解决方案是不要求批处理在日期上做算术运算(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 个目录。即使没有新的备份来替换它们,您也可以通过其他方式删除最旧的副本。
希望这对您有所帮助
对于初始脚本,使用 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
因为你的日期格式是可排序和可比较的,所以我会使用:
@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