【问题标题】:Batch Script to delete oldest folder in a given folder用于删除给定文件夹中最旧文件夹的批处理脚本
【发布时间】:2015-02-11 23:31:17
【问题描述】:

我正在编写一个简单的 .bat 备份脚本,作为其中的一部分,我希望在达到设置的最大备份限制时删除最旧的备份(文件夹)。

现在我有这个:

%COUNTER% 是基于当前存储备份的目录中的备份文件夹的数量,并在脚本前面计算。

%MAXBACKUPS% 只是一个用户指定的数字,例如“10”,表示您只想保留最多 10 个版本的备份。

:: Delete the oldest backup, but only if we've exceeded the desired number of backups.
IF %COUNTER% gtr %MAXBACKUPS% (
ECHO More than %MAXBACKUPS% backups exist. Deleting oldest...
FOR /f "delims=" %%a in ('dir "..\Backup\*" /t:c /a:d /o:-d /b') do rd /s /q "..\Backup\%%a"
::Increment the counter down since we've just removed a backup folder.
SET /a COUNTER=%COUNTER%-1
)

我希望此脚本仅删除 ..\Backup 文件夹中最旧的一个文件夹,但就目前而言,一旦达到备份限制,它似乎会删除找到的每个文件夹,这显然不是所需的行为。

【问题讨论】:

  • 好吧,脚本会删除每个文件夹,因为你有一个循环,它为每个文件夹调用 rd。这就是for 命令的作用。为什么要这样写?
  • 我以为我需要按日期正确排序所有文件夹,但现在我想起来,可能不是这样。
  • 事实证明确实如此,但我最初的做法有点不对劲。

标签: batch-file cmd


【解决方案1】:

你离得太近了! :-)

您只需在按日期降序排序时跳过第一个%MAXBACKUPS% 条目。你甚至不需要你的 COUNTER 变量。

:: Preserve only the %MAXBACKUPS% most recent backups.
set "delMsg="
for /f "skip=%MAXBACKUPS% delims=" %%a in (
  'dir "..\Backup\*" /t:c /a:d /o:-d /b'
) do (
  if not defined delMsg (
    set delMsg=1
    echo More than %MAXBACKUPS% found - only the %MAXBACKUPS% most recent folders will be preserved.
  )
  rd /s /q "..\Backup\%%a"
)

【讨论】:

  • 我认为这是实现它的最佳方式,尤其是因为它不需要计数器,并且如果您以后降低备份限制,可以删除额外的备份。我对我的实现做了一些细微的修改,我将在单独的答案中展示给感兴趣的人。
  • 你能再解释一下代码吗?我正在努力完成同样的工作,但我似乎无法开始工作。我每晚都在备份一个 SQL 数据库,我想删除第 5 个文件。我的文件夹结构是 E:\backups\NC\ 一堆文件。 NC_1、NC_2 等。我正在尝试保留最新的 4 个文件。
  • @Victor_Tlepshev - 此答案旨在满足 OP 的要求,即删除除 N 个最近的 文件夹 之外的所有文件夹。通过将dir更改为使用/a:-d并将rd /s /q更改为del,修改删除文件应该不难。如果您仍然遇到问题,请发布新问题。
【解决方案2】:

根据您的脚本执行此操作的简单方法:

FOR /f "delims=" %%a in ('dir "..\Backup\*" /t:c /a:d /o:-d /b') do set lastfolder=%%a

rd /s /q "..\Backup\%lastfolder%"

所以你仍然循环遍历每个文件夹,按年龄排序,但是你覆盖 %lastfolder% 所以最后它只包含最旧文件夹的名称。

然后你删除那个文件夹。

【讨论】:

  • 我在您建议的 FOR 行之后放置了 ECHO %LASTFOLDER%,但它报告 ECHO is off. 好像在 for 循环结束时该变量中没有存储任何内容。您可能无法访问在 for 循环中设置的变量吗?如果可以的话,还有其他问题在起作用。
  • 它适用于我的系统。如果有疑问,请将echo 放在do 之后(或者只是删除脚本开头的任何echo off),这样您就可以看到哪个set 是最后一个执行的。 Batch 没有变量的局部作用域,循环内的所有变量都可以从任何地方访问。
【解决方案3】:

这是我最终使用的最后一段代码:

:: Preserve only the %MAXBACKUPS% most recent backups.
FOR /f "skip=%MAXBACKUPS% delims=" %%a in (
'dir "..\Backup\*" /t:c /a:d /o:-d /b'
) do (
ECHO More than %MAXBACKUPS% backups found--Deleting "%%a".
ECHO.
rd /s /q "..\Backup\%%a"
)

它稍微简化了删除消息代码,并在命令提示符窗口中向最终用户提供有关删除了哪些文件的信息。

基于dbenham's answer.

【讨论】:

    【解决方案4】:
    FOR /f "delims=" %%a in ('dir "..\Backup\*" /t:c /a:d /o:d /b') do (
     rd /s /q "..\Backup\%%a"
     goto :break
    )
    :break
    

    你可以用 goto 打破 for 循环

    【讨论】: