Batch file 如何删除包含多个文件夹组的文件夹中一组文件夹中最旧的文件夹?

Batch file 如何删除包含多个文件夹组的文件夹中一组文件夹中最旧的文件夹?,batch-file,Batch File,文件夹D:\Backup包含下面列出的子文件夹,其名称(左)和上次修改日期(右)显示在Windows资源管理器中: 20171113.224424 15.11.2017 17:24 20171113.224421 16.11.2017 15:26 20171113.224412 16.11.2017 15:33 20171112.424424 16.11.2017 15:33 20171112.224424 16.1

文件夹
D:\Backup
包含下面列出的子文件夹,其名称(左)和上次修改日期(右)显示在Windows资源管理器中:

20171113.224424         15.11.2017 17:24
20171113.224421         16.11.2017 15:26
20171113.224412         16.11.2017 15:33
20171112.424424         16.11.2017 15:33
20171112.224424         16.11.2017 15:33
20171112.221424         16.11.2017 15:34
20171111.224428         16.11.2017 15:34
20171111.224427         16.11.2017 15:35
20171111.224424         16.11.2017 15:34
我需要一个批处理脚本来检查文件夹名称中是否有两个以上的文件夹具有相同的日期字符串,并且始终保留8位数字,如
20171113.224424
20171113.224421
20171113.224412

批处理文件应保留具有相同日期字符串的最新两个文件夹,并使用文件夹创建日期而不是上次修改日期删除所有其他较旧的文件夹

对于上面的示例,创建日期等于上次修改日期,要删除的文件夹为:

20171113.224424
20171112.224424
20171111.224424
当两个文件夹具有相同的创建日期时,如果可能的话,应删除点后数字较小的文件夹

其余文件夹为:

20171113.224421
20171113.224412
20171112.424424
20171112.221424
20171111.224428
20171111.224427
我尝试了很多代码,但我没有把它们全部发布在这里

我有列出目录中所有文件夹的代码,但找不到将前8个字母相同的文件夹分组的方法:

@echo off
set back=%cd%
for /d %%i in (d:\backup\*) do (
    cd "%%i"
    echo current directory:
    cd
    pause
)
cd %back%
我编写了代码,如果有常规分组,则跳过最后10行,并删除我不需要的文件夹,如上所述:

@echo off
for /F "skip=10 delims=" %%I in ('dir "d:\backup\*" /AD /B /O-N 2^>nul') do rd /Q /S "d:\backup\%%I"

此任务的批处理文件将是:

@echo off
setlocal EnableExtensions EnableDelayedExpansion
set "BackupFolder=D:\backup"
set "LastDate="
for /F "delims=." %%I in ('dir "%BackupFolder%\????????.*" /AD /B /ON 2^>nul') do (
    if not "!LastDate!" == "%%I" (
        for /F "skip=2 delims=" %%D in ('dir "%BackupFolder%\%%I.*" /AD /B /O-D-N /TC') do rd /Q /S "%BackupFolder%\%%D"
        set "LastDate=%%I"
    )
)
endlocal
第一个外部FOR在一个单独的命令过程中执行,该命令过程从第一个括号中指定的DIR命令行的后台
cmd/c
开始,并捕获DIR输出的所有内容,以处理STDOUT,以便以后逐行处理

使用的DIR命令输出

  • 由于
    /AD
    (属性目录),仅目录与通配符模式匹配
  • 由于
    /B
    (裸格式),仅使用其名称而没有路径
  • 因上的(按名称排序)而按名称排序
备份文件夹当前可能不包含与此模式匹配的文件夹。在这种情况下,DIR将输出一条错误消息来处理STDERR,这会让人感到困惑,因为它包含的是文件而不是目录。此可能的错误消息被重定向到设备NUL,以抑制它

阅读Microsoft关于的文章,了解有关
2>nul
的解释。当Windows命令解释器在执行的命令之前处理该命令行时,重定向操作符必须使用上的插入符号^进行转义,以便命令行被解释为文字字符,该命令在单独的命令中执行目录命令行进程在后台启动

外部FOR处理捕获的行,忽略空行和以分号开头的行。这里不存在这样的线路,所以没有问题。使用
作为分隔符,将每行(另一行)拆分为两个字符串。只有每行的第一个
左边的第一个字符串被分配给循环变量
I
,该变量在接下来执行的命令行中使用

在这里,使用命令DIR获取由处理的目录列表非常重要,因为在循环执行期间,不会被修改,而不是使用
FOR/D
,它将在循环的每次迭代中直接从文件系统读取下一个目录名。目录列表在循环执行期间发生更改。在为/D使用
时,可能会发生由于处理目录时目录列表发生更改而跳过某些目录的情况

IF条件使用延迟环境变量展开进行简单的区分大小写的字符串比较,以比较先前处理的文件夹的日期字符串与当前文件夹。只有在最后处理的文件夹的日期和当前文件夹的日期之间存在差异时,才会执行内部循环。此IF条件仅用于加快文件夹删除过程

在这里使用延迟环境变量展开是没有问题的,因为备份文件夹中没有文件夹在文件夹名称中包含感叹号

第二个,内部FOR循环也运行命令DIR,以获取目录列表,其中包含当前文件夹的日期字符串以及它们的名称,但是,由于
/O-D-N
(按日期排序,下一次按名称排序)和
/TC
(时间:创建),这一次第一次按创建日期排序,第二次按名称排序,如果两个或多个文件夹具有相同的创建日期。反向日期顺序意味着最新目录首先输出,最旧目录最后输出

内部FOR循环处理DIR输出的捕获行,跳过前两行,这意味着忽略两个最新文件夹。由于
delims=
(空分隔符列表),处理其他行时不会将行拆分,因此DIR输出的完整文件夹名被分配给循环变量
D

由于
/Q
,命令RD会悄悄删除名称为hold in loop变量
D
的文件夹以及由于
/S
而保留的所有文件和子文件夹

然后将当前文件夹的日期字符串分配给环境变量
LastDate
,以跳过外部目录列表中具有相同日期字符串的所有文件夹

也可以使用单个命令行,而不使用延迟的环境变量扩展,这会稍微慢一点,这也适用于具有
的文件夹在名称中

@for /F "delims=." %%I in ('dir "D:\backup\????????.*" /AD /B /ON 2^>nul') do @for /F "skip=2 delims=" %%D in ('dir "D:\backup\%%I.*" /AD /B /O-D-N /TC') do @rd /Q /S "D:\backup\%%D"
要了解所使用的命令及其工作方式,请打开命令提示窗口,在其中执行
@echo off
setlocal EnableExtensions EnableDelayedExpansion
set "BackupFolder=D:\backup"
set "LastDate="
set "LogFile=%BackupFolder%\DeletedFiles.log"
for /F "delims=." %%I in ('dir "%BackupFolder%\????????.*" /AD /B /ON 2^>nul') do (
    if not "!LastDate!" == "%%I" (
        for /F "skip=2 delims=" %%D in ('dir "%BackupFolder%\%%I.*" /AD /B /O-D-N /TC') do (
            dir "%BackupFolder%\%%D" /A-D /B /ON /S >>"%LogFile%" 2>nul
            rd /Q /S "%BackupFolder%\%%D"
        )
        set "LastDate=%%I"
    )
)
endlocal
@for /F "delims=." %%I in ('dir "D:\backup\????????.*" /AD /B /ON 2^>nul') do @for /F "skip=2 delims=" %%D in ('dir "D:\backup\%%I.*" /AD /B /O-D-N /TC') do @dir "D:\backup\%%D" /A-D /B /ON /S >>"D:\backup\DeletedFiles.log" 2>nul & rd /Q /S "D:\backup\%%D"