Windows 如何使用于删除旧文件的批处理脚本正常工作?

Windows 如何使用于删除旧文件的批处理脚本正常工作?,windows,file,batch-file,scripting,Windows,File,Batch File,Scripting,在文件夹(比如c:\test)中,如果文件数超过21,我想删除最旧的文件 这就是我想到的,问题是它一次删除最旧的文件,第二次运行它什么也不做,第三次删除最旧的文件,继续这样。此外,它不关心文件量是否低于21,即使文件量低于21,也会删除 代码如下: SET BACKUPDIR=C:\test SET countfiles=dir BACKUPDIR /b | find /v /c "::" if countfiles GTR 21 ( FOR /F %%i IN ('DIR /B /O-D %

在文件夹(比如c:\test)中,如果文件数超过21,我想删除最旧的文件

这就是我想到的,问题是它一次删除最旧的文件,第二次运行它什么也不做,第三次删除最旧的文件,继续这样。此外,它不关心文件量是否低于21,即使文件量低于21,也会删除

代码如下:

SET BACKUPDIR=C:\test
SET countfiles=dir BACKUPDIR /b | find /v /c "::"

if countfiles GTR 21 (
FOR /F %%i IN ('DIR /B /O-D %BACKUPDIR%') DO SET OLDEST=%%i
DEL %BACKUPDIR%\%OLDEST%
)

这有很多问题

  • 环境变量与文字字符串:

    SET countfiles=dir BACKUPDIR /b | find /v /c "::"
    
    在这里,您试图列出名为“BACKUPDIR”的目录中的文件,而不是使用环境变量。应该是

    SET countfiles=dir %BACKUPDIR% /b | find /v /c "::"
    
  • 您获取文件数的尝试:

    SET countfiles=dir %BACKUPDIR% /b | find /v /c "::"
    
    不可能工作。这只是分配字符串
    “dir BACKUPDIR/b | find/v/c”:
    “
    到环境变量
    countfiles
    。它不会运行任何东西,
    cmd
    如何知道这是要执行的命令

    您需要的是以下内容:

    for /f %%x in ('dir %BACKUPDIR% /b ^| find /v /c "::"') do set countfiles=%%x
    
    SET BACKUPDIR=C:\test
    for /f %%x in ('dir %BACKUPDIR% /b ^| find /v /c "::"') do set countfiles=%%x
    
    if %countfiles% GTR 21 (
        FOR /F "delims=" %%i IN ('DIR /B /O-D %BACKUPDIR%') DO SET OLDEST=%%i
        DEL %BACKUPDIR%\!OLDEST!
    )
    
    这将把
    countfiles
    环境变量的内容设置为上述命令的输出。你可以在中找到更多关于这方面的信息

  • 你的比较:

    if countfiles GTR 21
    
    这将比较字符串
    “countfiles”
    和字符串
    “21”
    。由于
    countfiles
    21
    之后排序,因此该条件始终为真

    您想在此处使用环境变量
    %countfiles%

    if %countfiles% GTR 21
    
  • 在“块”内尝试“普通”变量展开:

    由于
    cmd
    在解析命令时会立即展开环境变量,因此会导致问题。请注意,像上面这样的块被算作
    cmd
    的单个命令。整个块将在运行前被解析,并且在运行时已经替换了其中的所有变量,因此这不是处理该块中可能发生更改的变量的正确方法

    这里的解决方案是延迟扩展。可以在批处理开始时包含以下行:

    setlocal enabledelayedexpansion
    
    您使用的不是像
    %OLDEST%
    这样的变量!老大
    也展开变量,但直接在执行之前展开,而不是在解析时展开。因此,您的代码片段将变成:

    if %countfiles% GTR 21 (
        FOR /F %%i IN ('DIR /B /O-D %BACKUPDIR%') DO SET OLDEST=%%i
        DEL %BACKUPDIR%\!OLDEST!
    )
    
  • 为了防止您希望文件名带有空格,最后一个块中的
    for/f
    循环无法按预期工作。您可以这样修改它:

    for /f "delims=" %%i in ...
    
    这确保了行不会在空格处断开(您只会得到第一个标记,直到文件名中的第一个空格,而不是完整的文件名)

  • 总之,您的程序可能如下所示:

    for /f %%x in ('dir %BACKUPDIR% /b ^| find /v /c "::"') do set countfiles=%%x
    
    SET BACKUPDIR=C:\test
    for /f %%x in ('dir %BACKUPDIR% /b ^| find /v /c "::"') do set countfiles=%%x
    
    if %countfiles% GTR 21 (
        FOR /F "delims=" %%i IN ('DIR /B /O-D %BACKUPDIR%') DO SET OLDEST=%%i
        DEL %BACKUPDIR%\!OLDEST!
    )
    
    我还没有测试过它的每一个方面(床上通话),但我相信它比以前工作得更好,我希望你理解上面的修复以及为什么它们是必要的

    顺便说一句:
    find/v/c:“
    是一个漂亮的小把戏。我不知道也没想到


    以防万一:如果你真的想继续删除最旧的文件,直到你的文件数降到21以下,那么那一个
    If
    就不会删除它。你需要建立一个循环,或者继续迭代并重新计算每次迭代的次数,或者只是计算你必须删除的文件数。不过,我将把它作为一个练习。(提示:循环可以通过标签和条件
    goto
    s或使用
    for/l
    来完成。不过,后一个循环需要更多的延迟扩展,因此要小心。)

    这方面存在许多问题

  • 环境变量与文字字符串:

    SET countfiles=dir BACKUPDIR /b | find /v /c "::"
    
    在这里,您试图列出名为“BACKUPDIR”的目录中的文件,而不是使用环境变量

    SET countfiles=dir %BACKUPDIR% /b | find /v /c "::"
    
  • 您获取文件数的尝试:

    SET countfiles=dir %BACKUPDIR% /b | find /v /c "::"
    
    不可能工作。这只是分配字符串
    “dir BACKUPDIR/b | find/v/c”:
    “
    到环境变量
    countfiles
    。它不会运行任何东西
    cmd
    如何知道这是要执行的命令

    您需要的是以下内容:

    for /f %%x in ('dir %BACKUPDIR% /b ^| find /v /c "::"') do set countfiles=%%x
    
    SET BACKUPDIR=C:\test
    for /f %%x in ('dir %BACKUPDIR% /b ^| find /v /c "::"') do set countfiles=%%x
    
    if %countfiles% GTR 21 (
        FOR /F "delims=" %%i IN ('DIR /B /O-D %BACKUPDIR%') DO SET OLDEST=%%i
        DEL %BACKUPDIR%\!OLDEST!
    )
    
    这将把
    countfiles
    环境变量的内容设置为上述命令的输出。您可以使用找到更多关于这方面的信息

  • 你的比较:

    if countfiles GTR 21
    
    这将比较字符串
    “countfiles”
    和字符串
    “21”
    。由于
    countfiles
    21
    之后排序,因此此条件始终为真

    您想在此处使用环境变量
    %countfiles%

    if %countfiles% GTR 21
    
  • 在“块”内尝试“普通”变量展开:

    由于
    cmd
    在解析命令时会立即扩展环境变量,这会导致问题。请注意,上面这样的块被视为
    cmd
    的单个命令。整个块在运行前会被解析,并且在运行时已替换了其中的所有变量,因此这不是处理变量的正确方法可能在该区块内发生变化的数据

    这里的解决方案是延迟扩展。您可以在批处理开始时包括以下行:

    setlocal enabledelayedexpansion
    
    您使用的不是像
    %OLDEST%
    这样的变量,而是
    !OLDEST!
    也会展开变量,但在执行前直接展开变量,而不是在解析时展开变量。因此,您的代码段将变成:

    if %countfiles% GTR 21 (
        FOR /F %%i IN ('DIR /B /O-D %BACKUPDIR%') DO SET OLDEST=%%i
        DEL %BACKUPDIR%\!OLDEST!
    )
    
  • 为了防止您希望文件名带有空格,最后一个块中的
    for/f
    循环无法按预期工作。您可以这样修改它:

    for /f "delims=" %%i in ...
    
    这确保了行不会在空格处断开(您只会得到第一个标记,直到文件名中的第一个空格,而不是完整的文件名)

  • 总之,您的程序可能如下所示:

    for /f %%x in ('dir %BACKUPDIR% /b ^| find /v /c "::"') do set countfiles=%%x
    
    SET BACKUPDIR=C:\test
    for /f %%x in ('dir %BACKUPDIR% /b ^| find /v /c "::"') do set countfiles=%%x
    
    if %countfiles% GTR 21 (
        FOR /F "delims=" %%i IN ('DIR /B /O-D %BACKUPDIR%') DO SET OLDEST=%%i
        DEL %BACKUPDIR%\!OLDEST!
    )
    
    我还没有测试过它的每一个方面(床上通话),但我相信它比以前和现在工作得更好