如何删除文件夹中最旧的文件?

时间:2018-08-07 19:08:39

标签: batch-file batch-processing

我正在编写一个用于备份文件的批处理脚本,并且想要包含一种逻辑,如果备份数超过某个变量设置的某个特定数,该逻辑将删除文件夹中最旧的文件。批处理很新,一旦超出数量,我当前的代码就会删除所有文件。

任何想法如何做到这一点?

SET Count=0
FOR %%A IN ("%SNAPSHOTNAME%*.*") DO SET /A Count += 1
IF %Count% gtr %NumberOfBackups% FOR %%A IN ("%SNAPSHOTNAME%_PBCS_Test_*.*") DO del "%%A"

3 个答案:

答案 0 :(得分:2)

对于此任务,我建议使用以下单个命令行:

for /F "skip=%NumberOfBackups% eol=| delims=" %%I in ('dir "%SNAPSHOTNAME%_PBCS_Test_*.*" /A-D-H /B /O-D 2^>nul') do del "%%I"

FOR 在后台以cmd.exe /C开头的命令行中执行单独的命令过程:

dir "%SNAPSHOTNAME%_PBCS_Test_*.*" /A-D-H /B /O-D 2>nul

DIR 输出可逐行处理 STDOUT

  • 由于/A-D-H而不是隐藏文件(不是属性目录或隐藏文件)
  • 由于/B而以裸格式显示,这意味着仅文件名
  • 按最后修改(写入)时间的顺序排序,最新的文件优先,最旧的文件最后。

DIR 输出的用于处理 STDERR 的错误消息是通过使用2>nul将其重定向到设备 NUL 来抑制的。

也请阅读有关Using Command Redirection Operators的Microsoft文章,以获取2>nul的解释。当Windows命令解释器在执行命令之前处理此命令行时,重定向操作符>必须在 FOR 命令行上使用脱字符号^进行转义,才能被解释为文字字符。 FOR ,它将在后台启动的单独命令进程中执行嵌入式dir命令行。

FOR 捕获此输出并根据双引号字符串中指定的选项逐行处理它,而忽略 DIR 的输出中不存在的空行

FOR 跳过了前%NumberOfBackups%行,这意味着最新的%NumberOfBackups%始终保留在当前目录中。

FOR 默认情况下也会忽略以分号开头的行,因为;是行尾字符的默认设置。因此,eol=|用于将行尾字符更改为竖线,这在文件或文件夹名称中是不可能的,因此 DIR 输出的文件名不可能以|

FOR 默认情况下,使用常规空格和水平制表符作为字符串定界符将行拆分为子字符串,并仅将第一个空格/制表符分隔的字符串分配给循环变量I。可以通过在选项字符串末尾用delims=指定一个空的定界符列表来获取分配给循环变量I的整行(=文件名)来禁用此字符串拆分行为。

因此 DIR 会逐行输出所有匹配模式"%SNAPSHOTNAME%_PBCS_Test_*.*"且名称为最新的文件,最后是最早的文件的所有非隐藏文件的名称,而 FOR 会忽略名称/最新的%NumberOfBackups%文件,并删除所有其他较旧的文件。

如果 DIR 输出的文件名少于或完全%NumberOfBackups%,则

FOR 不执行任何操作。

要了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读每个命令显示的所有帮助页面。

  • del /?
  • dir /?
  • for /?

注意:这与Squashman所写的答案几乎相同,但有完整的解释。

答案 1 :(得分:1)

您的第二个for循环没有排序,也没有中断条件,因此正如您所提到的,它将删除所有文件。

dir命令可以对文件进行排序,因此,取代对所有文件使用for而不对for命令的排序输出使用dir。选项/OD将按文件时间戳排序。

要让for循环处理输出,请使用for /f。中断条件是仅删除第一个(在这种情况下为最旧的)文件,然后跳出for循环。

IF %Count% gtr %NumberOfBackups% for /f "delims=" %%f in ('dir /B /OD "%SNAPSHOTNAME%_PBCS_Test_*.*"') do del "%%f" & goto :gotIt
:gotIt

答案 2 :(得分:1)

如果使用带有SKIP选项的FOR / F命令,可以摆脱IF比较。

set "NumberOfBackups=6"
FOR /F "SKIP=%NumberOfBackups% DELIMS=" %%G IN ('DIR /A-D /B /O-D "%SNAPSHOTNAME%_PBCS_Test_*.*"') DO DEL "%%G"