首页 文章

批处理文件,用于删除超过N天的文件

提问于
浏览
619

我正在寻找一种方法来删除批处理文件中超过7天的所有文件 . 我在网上搜索过,发现了一些包含数百行代码的示例,还有一些需要安装额外的命令行实用程序才能完成任务 .

只需几行代码,类似的东西就可以done in BASH . 对于Windows中的批处理文件,似乎至少可以轻松实现 . 我正在寻找一个在标准Windows命令提示符下工作的解决方案,没有任何额外的实用程序 . 请不要使用PowerShell或Cygwin .

23 回答

  • 7

    对于Windows 2012 R2,以下方法可行:

    forfiles /p "c:\FOLDERpath" /d -30 /c "cmd /c del @path"
    

    查看将被删除的文件使用此

    forfiles /p "c:\FOLDERpath" /d -30 /c "cmd /c echo @path @fdate"
    
  • 16

    对于Windows Server 2008 R2:

    forfiles /P c:\sql_backups\ /S /M *.sql /D -90 /C "cmd /c del @PATH"
    

    这将删除超过90天的所有.sql文件 .

  • 5

    IMO,JavaScript逐渐成为一种通用的脚本标准:它可能在比其他任何脚本语言更多的产品中可用(在Windows中,它可以使用Windows Scripting Host) . 我必须清理许多文件夹中的旧文件,所以这里有一个JavaScript函数:

    // run from an administrator command prompt (or from task scheduler with full rights):  wscript jscript.js
    // debug with:   wscript /d /x jscript.js
    
    var fs = WScript.CreateObject("Scripting.FileSystemObject");
    
    clearFolder('C:\\temp\\cleanup');
    
    function clearFolder(folderPath)
    {
        // calculate date 3 days ago
        var dateNow = new Date();
        var dateTest = new Date();
        dateTest.setDate(dateNow.getDate() - 3);
    
        var folder = fs.GetFolder(folderPath);
        var files = folder.Files;
    
        for( var it = new Enumerator(files); !it.atEnd(); it.moveNext() )
        {
            var file = it.item();
    
            if( file.DateLastModified < dateTest)
            {
                var filename = file.name;
                var ext = filename.split('.').pop().toLowerCase();
    
                if (ext != 'exe' && ext != 'dll')
                {
                    file.Delete(true);
                }
            }
        }
    
        var subfolders = new Enumerator(folder.SubFolders);
        for (; !subfolders.atEnd(); subfolders.moveNext())
        {
            clearFolder(subfolders.item().Path);
        }
    }
    

    对于要清除的每个文件夹,只需向clearFolder()函数添加另一个调用 . 此特定代码还保留exe和dll文件,并清理子文件夹 .

  • 5

    如果您有XP资源工具包,则可以使用robocopy将所有旧目录移动到单个目录中,然后使用rmdir删除该目录:

    mkdir c:\temp\OldDirectoriesGoHere
    robocopy c:\logs\SoManyDirectoriesToDelete\ c:\temp\OldDirectoriesGoHere\ /move /minage:7
    rmdir /s /q c:\temp\OldDirectoriesGoHere
    
  • 3

    我可能会为这个已经很有 Value 的线程添加一份不起眼的贡献 . 我发现其他解决方案可能会删除实际的错误文本,但忽略了%ERRORLEVEL%,这表示我的应用程序出现故障 . 只要它不是“找不到文件”错误,我合法地想要%ERRORLEVEL% .

    Some Examples:

    Debugging and eliminating the error specifically:

    forfiles /p "[file path...]\IDOC_ARCHIVE" /s /m *.txt /d -1 /c "cmd /c del @path" 2>&1 |  findstr /V /O /C:"ERROR: No files found with the specified search criteria."2>&1 | findstr ERROR&&ECHO found error||echo found success
    

    Using a oneliner to return ERRORLEVEL success or failure:

    forfiles /p "[file path...]\IDOC_ARCHIVE" /s /m *.txt /d -1 /c "cmd /c del @path" 2>&1 |  findstr /V /O /C:"ERROR: No files found with the specified search criteria."2>&1 | findstr ERROR&&EXIT /B 1||EXIT /B 0
    

    Using a oneliner to keep the ERRORLEVEL at zero for success within the context of a batchfile in the midst of other code (ver > nul resets the ERRORLEVEL):

    forfiles /p "[file path...]\IDOC_ARCHIVE" /s /m *.txt /d -1 /c "cmd /c del @path" 2>&1 |  findstr /V /O /C:"ERROR: No files found with the specified search criteria."2>&1 | findstr ERROR&&ECHO found error||ver > nul
    

    For a SQL Server Agent CmdExec job step I landed on the following. I don't know if it's a bug, but the CmdExec within the step only recognizes the first line of code:

    cmd /e:on /c "forfiles /p "C:\SQLADMIN\MAINTREPORTS\SQL2" /s /m *.txt /d -1 /c "cmd /c del @path" 2>&1 |  findstr /V /O /C:"ERROR: No files found with the specified search criteria."2>&1 | findstr ERROR&&EXIT 1||EXIT 0"&exit %errorlevel%
    
  • 2
    forfiles /p "v:" /s /m *.* /d -3 /c "cmd /c del @path"
    

    你应该做 /d -3 (3天前)这对我来说很好 . 因此,所有复杂的批次都可能在垃圾桶中 . 此外 forfiles 不支持UNC路径,因此请与特定驱动器 Build 网络连接 .

  • 2

    看看我的answersimilar question

    REM del_old.bat
    REM usage: del_old MM-DD-YYY
    for /f "tokens=*" %%a IN ('xcopy *.* /d:%1 /L /I null') do if exist %%~nxa echo %%~nxa >> FILES_TO_KEEP.TXT
    for /f "tokens=*" %%a IN ('xcopy *.* /L /I /EXCLUDE:FILES_TO_KEEP.TXT null') do if exist "%%~nxa" del "%%~nxa"
    

    这将删除早于给定日期的文件 . 我确信它可以修改为从当前日期开始七天 .

    update: 我注意到HerbCSO对上述脚本进行了改进 . 我建议改用his version .

  • 5

    批处理文件通常需要解决与日期/时间相关的相关问题 . 但命令行解释器 cmd.exe 没有日期/时间计算功能 . 已经在此处,Stack Overflow的其他页面以及其他网站上发布了许多使用其他控制台应用程序或脚本的良好工作解决方案 .

    基于日期/时间的操作的共同点是要求将日期/时间字符串转换为自确定日期以来的秒数 . 很常见的是1970-01-01 00:00:00 UTC . 但是,根据支持特定任务所需的日期范围,也可以使用任何后续日期 .

    Jay发布7daysclean.cmd包含命令行解释器 cmd.exe 的快速"date to seconds"解决方案 . 但它并没有将闰年考虑在内 . J.R.考虑了当前年度的闰日,但忽略了自基准年以来的其他闰年,即自1970年以来 .

    我使用20年来使用一个小C函数创建一次的静态表(数组),用于快速获取包含在C / C中编写的应用程序中日期/时间转换函数中1970-01-01的闰日的天数 .

    这种非常快速的表方法也可以使用 FOR 命令在批处理代码中使用 . 所以我决定编写批处理子程序 GetSeconds ,它计算自1970-01-01 00:00:00 UTC以来传递给该例程的日期/时间字符串的秒数 .

    Note: 由于Windows文件系统也不支持闰秒,因此不考虑闰秒 .

    首先,表格:

    • 自1970-01-01 00:00:00以来每天的UTC,包括闰日 .
    1970 - 1979:     0   365   730  1096  1461  1826  2191  2557  2922  3287
    1980 - 1989:  3652  4018  4383  4748  5113  5479  5844  6209  6574  6940
    1990 - 1999:  7305  7670  8035  8401  8766  9131  9496  9862 10227 10592
    2000 - 2009: 10957 11323 11688 12053 12418 12784 13149 13514 13879 14245
    2010 - 2019: 14610 14975 15340 15706 16071 16436 16801 17167 17532 17897
    2020 - 2029: 18262 18628 18993 19358 19723 20089 20454 20819 21184 21550
    2030 - 2039: 21915 22280 22645 23011 23376 23741 24106 24472 24837 25202
    2040 - 2049: 25567 25933 26298 26663 27028 27394 27759 28124 28489 28855
    2050 - 2059: 29220 29585 29950 30316 30681 31046 31411 31777 32142 32507
    2060 - 2069: 32872 33238 33603 33968 34333 34699 35064 35429 35794 36160
    2070 - 2079: 36525 36890 37255 37621 37986 38351 38716 39082 39447 39812
    2080 - 2089: 40177 40543 40908 41273 41638 42004 42369 42734 43099 43465
    2090 - 2099: 43830 44195 44560 44926 45291 45656 46021 46387 46752 47117
    2100 - 2106: 47482 47847 48212 48577 48942 49308 49673
    

    使用无符号的32位变量(即C / C中的无符号长整数(或无符号整数)),只能在1970-01-01开始时计算2039年到2106年的秒数 .

    cmd.exe 用于数学表达式的带符号32位变量 . 因此最大值为2147483647(0x7FFFFFFF),即2038-01-19 03:14:07 .

    • 1970年至2106年的闰年信息(否/是) .
    1970 - 1989: N N Y N N N Y N N N Y N N N Y N N N Y N
    1990 - 2009: N N Y N N N Y N N N Y N N N Y N N N Y N
    2010 - 2029: N N Y N N N Y N N N Y N N N Y N N N Y N
    2030 - 2049: N N Y N N N Y N N N Y N N N Y N N N Y N
    2050 - 2069: N N Y N N N Y N N N Y N N N Y N N N Y N
    2070 - 2089: N N Y N N N Y N N N Y N N N Y N N N Y N
    2090 - 2106: N N Y N N N Y N N N N N N N Y N N
                                     ^ year 2100
    
    • 当年每月第一天的天数 .
    Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
    Year with 365 days:  0  31  59  90 120 151 181 212 243 273 304 334
    Year with 366 days:  0  31  60  91 121 152 182 213 244 274 305 335
    

    使用这些表格将日期转换为自1970-01-01以来的秒数非常简单 .

    Attention please!

    日期和时间字符串的格式取决于Windows区域和语言设置 . 如果需要,分配给 GetSeconds 的第一个 FOR 循环中的环境变量 DayMonthYear 的分隔符和标记顺序必须适应本地日期/时间格式 .

    如果环境变量 DATE 中的日期格式与日期格式不同,则必须调整环境变量的日期字符串在 %%~tF 上由命令 FOR 使用 .

    例如,当 %DATE% 扩展为 Sun 02/08/2015%%~tF 扩展为 02/08/2015 07:38 PM 时,以下代码可用于将第4行修改为:

    call :GetSeconds "%DATE:~4% %TIME%"
    

    这导致传递给子程序 02/08/2015 - 没有工作日缩写的3个字母和分隔空格字符的日期字符串 .

    或者,可以使用以下格式以正确的格式传递当前日期:

    call :GetSeconds "%DATE:~-10% %TIME%"
    

    现在,日期字符串中的最后10个字符被传递给函数 GetSeconds ,因此无论环境变量 DATE 的日期字符串是否有工作日都没关系,只要日期和月份总是以预期顺序的2位数,即格式为 dd/mm/yyyydd.mm.yyyy .

    这是批处理代码,用于解释注释,只输出要删除的文件以及保存在 C:\Temp 文件夹树中的文件,请参阅第一个 FOR 循环的代码 .

    @echo off
    setlocal EnableExtensions EnableDelayedExpansion
    rem Get seconds since 1970-01-01 for current date and time.
    call :GetSeconds "%DATE% %TIME%"
    rem Subtract seconds for 7 days from seconds value.
    set /A "LastWeek=Seconds-7*86400"
    
    rem For each file in each subdirectory of C:\Temp get last modification date
    rem (without seconds -> append second 0) and determine the number of seconds
    rem since 1970-01-01 for this date/time. The file can be deleted if seconds
    rem value is lower than the value calculated above.
    
    for /F "delims=" %%F in ('dir /A-D-H-S /B /S "C:\Temp"') do (
        call :GetSeconds "%%~tF:0"
        rem if !Seconds! LSS %LastWeek% del /F "%%~fF"
        if !Seconds! LEQ %LastWeek% (
            echo Delete "%%~fF"
        ) else (
            echo Keep   "%%~fF"
        )
    )
    endlocal
    goto :EOF
    
    
    rem No validation is made for best performance. So make sure that date
    rem and hour in string is in a format supported by the code below like
    rem MM/DD/YYYY hh:mm:ss or M/D/YYYY h:m:s for English US date/time.
    
    :GetSeconds
    
    rem If there is " AM" or " PM" in time string because of using 12 hour
    rem time format, remove those 2 strings and in case of " PM" remember
    rem that 12 hours must be added to the hour depending on hour value.
    
    set "DateTime=%~1"
    set "Add12Hours=0"
    if "%DateTime: AM=%" NEQ "%DateTime%" (
        set "DateTime=%DateTime: AM=%"
    ) else if "%DateTime: PM=%" NEQ "%DateTime%" (
        set "DateTime=%DateTime: PM=%"
        set "Add12Hours=1"
    )
    
    rem Get year, month, day, hour, minute and second from first parameter.
    
    for /F "tokens=1-6 delims=,-./: " %%A in ("%DateTime%") do (
        rem For English US date MM/DD/YYYY or M/D/YYYY
        set "Day=%%B" & set "Month=%%A" & set "Year=%%C"
        rem For German date DD.MM.YYYY or English UK date DD/MM/YYYY
        rem set "Day=%%A" & set "Month=%%B" & set "Year=%%C"
        set "Hour=%%D" & set "Minute=%%E" & set "Second=%%F"
    )
    rem echo Date/time is: %Year%-%Month%-%Day% %Hour%:%Minute%:%Second%
    
    rem Remove leading zeros from the date/time values or calculation could be wrong.
    if "%Month:~0,1%"  EQU "0" ( if "%Month:~1%"  NEQ "" set "Month=%Month:~1%"   )
    if "%Day:~0,1%"    EQU "0" ( if "%Day:~1%"    NEQ "" set "Day=%Day:~1%"       )
    if "%Hour:~0,1%"   EQU "0" ( if "%Hour:~1%"   NEQ "" set "Hour=%Hour:~1%"     )
    if "%Minute:~0,1%" EQU "0" ( if "%Minute:~1%" NEQ "" set "Minute=%Minute:~1%" )
    if "%Second:~0,1%" EQU "0" ( if "%Second:~1%" NEQ "" set "Second=%Second:~1%" )
    
    rem Add 12 hours for time range 01:00:00 PM to 11:59:59 PM,
    rem but keep the hour as is for 12:00:00 PM to 12:59:59 PM.
    if "%Add12Hours%" == "1" (
        if %Hour% LSS 12 set /A Hour+=12
    )
    set "DateTime="
    set "Add12Hours="
    
    rem Must use 2 arrays as more than 31 tokens are not supported
    rem by command line interpreter cmd.exe respectively command FOR.
    set /A "Index1=Year-1979"
    set /A "Index2=Index1-30"
    
    if %Index1% LEQ 30 (
        rem Get number of days to year for the years 1980 to 2009.
        for /F "tokens=%Index1% delims= " %%Y in ("3652 4018 4383 4748 5113 5479 5844 6209 6574 6940 7305 7670 8035 8401 8766 9131 9496 9862 10227 10592 10957 11323 11688 12053 12418 12784 13149 13514 13879 14245") do set "Days=%%Y"
        for /F "tokens=%Index1% delims= " %%L in ("Y N N N Y N N N Y N N N Y N N N Y N N N Y N N N Y N N N Y N") do set "LeapYear=%%L"
    ) else (
        rem Get number of days to year for the years 2010 to 2038.
        for /F "tokens=%Index2% delims= " %%Y in ("14610 14975 15340 15706 16071 16436 16801 17167 17532 17897 18262 18628 18993 19358 19723 20089 20454 20819 21184 21550 21915 22280 22645 23011 23376 23741 24106 24472 24837") do set "Days=%%Y"
        for /F "tokens=%Index2% delims= " %%L in ("N N Y N N N Y N N N Y N N N Y N N N Y N N N Y N N N Y N N") do set "LeapYear=%%L"
    )
    
    rem Add the days to month in year.
    if "%LeapYear%" == "N" (
        for /F "tokens=%Month% delims= " %%M in ("0 31 59 90 120 151 181 212 243 273 304 334") do set /A "Days+=%%M"
    ) else (
        for /F "tokens=%Month% delims= " %%M in ("0 31 60 91 121 152 182 213 244 274 305 335") do set /A "Days+=%%M"
    )
    
    rem Add the complete days in month of year.
    set /A "Days+=Day-1"
    
    rem Calculate the seconds which is easy now.
    set /A "Seconds=Days*86400+Hour*3600+Minute*60+Second"
    
    rem Exit this subroutine
    goto :EOF
    

    为获得最佳性能,最好删除所有注释,即在0-4前导空格后以 rem 开头的所有行 .

    并且阵列也可以做得更小,即减少从1980-01-01 00:00:00到2038-01-19 03:14:07的时间范围,如上面的批处理代码目前所支持的那样,例如2015-01 -01到2019-12-31,如下面的代码所用,它真正删除 C:\Temp 文件夹树中超过7天的文件 .

    此外,下面的批次代码针对24小时时间格式进行了优化 .

    @echo off
    setlocal EnableDelayedExpansion
    call :GetSeconds "%DATE:~-10% %TIME%"
    set /A "LastWeek=Seconds-7*86400"
    
    for /F "delims=" %%F in ('dir /A-D-H-S /B /S "C:\Temp"') do (
        call :GetSeconds "%%~tF:0"
        if !Seconds! LSS %LastWeek% del /F "%%~fF"
    )
    endlocal
    goto :EOF
    
    :GetSeconds
    for /F "tokens=1-6 delims=,-./: " %%A in ("%~1") do (
        set "Day=%%B" & set "Month=%%A" & set "Year=%%C"
        set "Hour=%%D" & set "Minute=%%E" & set "Second=%%F"
    )
    if "%Month:~0,1%"  EQU "0" ( if "%Month:~1%"  NEQ "" set "Month=%Month:~1%"   )
    if "%Day:~0,1%"    EQU "0" ( if "%Day:~1%"    NEQ "" set "Day=%Day:~1%"       )
    if "%Hour:~0,1%"   EQU "0" ( if "%Hour:~1%"   NEQ "" set "Hour=%Hour:~1%"     )
    if "%Minute:~0,1%" EQU "0" ( if "%Minute:~1%" NEQ "" set "Minute=%Minute:~1%" )
    if "%Second:~0,1%" EQU "0" ( if "%Second:~1%" NEQ "" set "Second=%Second:~1%" )
    set /A "Index=Year-2014"
    for /F "tokens=%Index% delims= " %%Y in ("16436 16801 17167 17532 17897") do set "Days=%%Y"
    for /F "tokens=%Index% delims= " %%L in ("N Y N N N") do set "LeapYear=%%L"
    if "%LeapYear%" == "N" (
        for /F "tokens=%Month% delims= " %%M in ("0 31 59 90 120 151 181 212 243 273 304 334") do set /A "Days+=%%M"
    ) else (
        for /F "tokens=%Month% delims= " %%M in ("0 31 60 91 121 152 182 213 244 274 305 335") do set /A "Days+=%%M"
    )
    set /A "Days+=Day-1"
    set /A "Seconds=Days*86400+Hour*3600+Minute*60+Second"
    goto :EOF
    

    有关Windows上的日期和时间格式以及文件时间比较的更多信息,请参阅Find out if file is older than 4 hours in batch file上的答案以及有关文件时间的大量其他信息 .

  • 3

    请享用:

    forfiles -p "C:\what\ever" -s -m *.* -d <number of days> -c "cmd /c del @path"
    

    有关详细信息,请参阅forfile documentation .

    有关更多好处,请参阅An A-Z Index of the Windows XP command line .

    如果您的计算机上没有安装 forfiles ,请将其从任何Windows Server 2003复制到您的Windows XP计算机 %WinDir%\system32\ . 这是可能的,因为EXE在Windows Server 2003和Windows XP之间完全兼容 .

    Windows和Windows Server的更高版本默认安装它 .

    对于Windows 7:

    语法稍有改变 . 因此更新的命令是:

    forfiles /p "C:\what\ever" /s /m *.* /D -<number of days> /C "cmd /c del @path"
    
  • 1

    使用forfiles .

    有不同的版本 . 早期使用unix样式参数 .

    我的版本(对于服务器2000 - 切换后没有空格) -

    forfiles -p"C:\what\ever" -s -m*.* -d<number of days> -c"cmd /c del @path"
    

    要向XP添加forfiles,请从ftp://ftp.microsoft.com/ResKit/y2kfix/x86/获取exe

    并将其添加到C:\ WINDOWS \ system32

  • 2

    Ok感到无聊并想出了这个,其中包含我的版本的穷人的Linux纪元更换限制为每日使用(没有时间保留):

    7daysclean.cmd

    @echo off
    setlocal ENABLEDELAYEDEXPANSION
    set day=86400
    set /a year=day*365
    set /a strip=day*7
    set dSource=C:\temp
    
    call :epoch %date%
    set /a slice=epoch-strip
    
    for /f "delims=" %%f in ('dir /a-d-h-s /b /s %dSource%') do (
        call :epoch %%~tf
        if !epoch! LEQ %slice% (echo DELETE %%f ^(%%~tf^)) ELSE echo keep %%f ^(%%~tf^)
    )
    exit /b 0
    
    rem Args[1]: Year-Month-Day
    :epoch
        setlocal ENABLEDELAYEDEXPANSION
        for /f "tokens=1,2,3 delims=-" %%d in ('echo %1') do set Years=%%d& set Months=%%e& set Days=%%f
        if "!Months:~0,1!"=="0" set Months=!Months:~1,1!
        if "!Days:~0,1!"=="0" set Days=!Days:~1,1!
        set /a Days=Days*day
        set /a _months=0
        set i=1&& for %%m in (31 28 31 30 31 30 31 31 30 31 30 31) do if !i! LSS !Months! (set /a _months=!_months! + %%m*day&& set /a i+=1)
        set /a Months=!_months!
        set /a Years=(Years-1970)*year
        set /a Epoch=Years+Months+Days
        endlocal& set Epoch=%Epoch%
        exit /b 0
    

    用法

    set /a strip=day*7 :将 7 更改为要保留的天数 .

    set dSource=C:\temp :这是检查文件的起始目录 .

    注意

    这是非破坏性代码,它将显示将要发生的事情 .

    变化:

    if !epoch! LEQ %slice% (echo DELETE %%f ^(%%~tf^)) ELSE echo keep %%f ^(%%~tf^)
    

    类似于:

    if !epoch! LEQ %slice% del /f %%f
    

    所以文件实际上被删除了

    February :硬编码为28天 . 真的,Bissextile年是一个地狱 . 如果某人有想法不会添加10行代码,请继续发布,然后将其添加到我的代码中 .

    epoch :我没有花时间考虑,因为需要删除早于某个日期的文件,花费数小时/分钟就会删除一天中用于保存的文件 .

    限制

    epoch 理所当然地认为您的短日期格式是YYYY-MM-DD . 它需要适用于其他设置或运行时评估(读取sShortTime,用户绑定配置,在过滤器中配置正确的字段顺序,并使用过滤器从参数中提取正确的数据) .

    我提到我讨厌这个编辑器的自动格式吗?它删除了空行,复制粘贴是一个地狱 .

    我希望这有帮助 .

  • 21

    我认为e.James's answer很好,因为它早在Windows 2000 SP4(可能更早)就可以使用未经修改的Windows版本,但它需要写入外部文件 . 这是一个修改后的版本,在保持兼容性的同时不会创建外部文本文件:

    REM del_old.cmd
    REM usage: del_old MM-DD-YYYY
    setlocal enabledelayedexpansion
    for /f "tokens=*" %%a IN ('xcopy *.* /d:%1 /L /I null') do @if exist "%%~nxa" set "excludefiles=!excludefiles!;;%%~nxa;;"
    for /f "tokens=*" %%a IN ('dir /b') do @(@echo "%excludefiles%"|FINDSTR /C:";;%%a;;">nul || if exist "%%~nxa" DEL /F /Q "%%a">nul 2>&1)
    

    为了忠实于原始问题,这里是一个脚本,如果你以天数作为参数调用它,它会为你做所有数学运算:

    REM del_old_compute.cmd
    REM usage: del_old_compute N
    setlocal enabledelayedexpansion
    set /a days=%1&set cur_y=%DATE:~10,4%&set cur_m=%DATE:~4,2%&set cur_d=%DATE:~7,2%
    for /f "tokens=1 delims==" %%a in ('set cur_') do if "!%%a:~0,1!"=="0" set /a %%a=!%%a:~1,1!+0
    set mo_2=28&set /a leapyear=cur_y*10/4
    if %leapyear:~-1% equ 0 set mo_2=29
    set mo_1=31&set mo_3=31&set mo_4=30&set mo_5=31
    set mo_6=30&set mo_7=31&set mo_8=31&set mo_9=30
    set mo_10=31&set mo_11=30&set mo_12=31
    set /a past_y=(days/365)
    set /a monthdays=days-((past_y*365)+((past_y/4)*1))&&set /a past_y=cur_y-past_y&set months=0
    :setmonth
    set /a minusmonth=(cur_m-1)-months
    if %minusmonth% leq 0 set /a minusmonth+=12
    set /a checkdays=(mo_%minusmonth%)
    if %monthdays% geq %checkdays% set /a months+=1&set /a monthdays-=checkdays&goto :setmonth
    set /a past_m=cur_m-months
    set /a lastmonth=cur_m-1
    if %lastmonth% leq 0 set /a lastmonth+=12
    set /a lastmonth=mo_%lastmonth%
    set /a past_d=cur_d-monthdays&set adddays=::
    if %past_d% leq 0 (set /a past_m-=1&set adddays=)
    if %past_m% leq 0 (set /a past_m+=12&set /a past_y-=1)
    set mo_2=28&set /a leapyear=past_y*10/4
    if %leapyear:~-1% equ 0 set mo_2=29
    %adddays%set /a past_d+=mo_%past_m%
    set d=%past_m%-%past_d%-%past_y%
    for /f "tokens=*" %%a IN ('xcopy *.* /d:%d% /L /I null') do @if exist "%%~nxa" set "excludefiles=!excludefiles!;;%%~nxa;;"
    for /f "tokens=*" %%a IN ('dir /b') do @(@echo "%excludefiles%"|FINDSTR /C:";;%%a;;">nul || if exist "%%~nxa" DEL /F /Q "%%a">nul 2>&1)
    

    注意:上面的代码考虑了闰年,以及每个月的确切天数 . 唯一的最大值是自0/0/0以来的总天数(之后它返回负数年) .

    注意:数学只有一种方式;它无法从负面输入中正确获取未来日期(它会尝试,但很可能会超过该月的最后一天) .

  • 0

    ROBOCOPY 对我很有用 . 最初建议我的伊曼 . 但不是将文件/文件夹移动到临时目录,而是删除临时文件夹的内容, move the files to the trash!!!

    这是我的备份批处理文件的几行,例如:

    SET FilesToClean1=C:\Users\pauls12\Temp
    SET FilesToClean2=C:\Users\pauls12\Desktop\1616 - Champlain\Engineering\CAD\Backups
    
    SET RecycleBin=C:\$Recycle.Bin\S-1-5-21-1480896384-1411656790-2242726676-748474
    
    robocopy "%FilesToClean1%" "%RecycleBin%" /mov /MINLAD:15 /XA:SH /NC /NDL /NJH /NS /NP /NJS
    robocopy "%FilesToClean2%" "%RecycleBin%" /mov /MINLAD:30 /XA:SH /NC /NDL /NJH /NS /NP /NJS
    

    它可清除“Temp”文件夹中超过15天的任何内容,并清除AutoCAD备份文件夹中的任何内容 . 我使用变量,因为行可以变得很长,我可以将它们重用于其他位置 . 您只需找到与您的登录相关联的回收站的dos路径 .

    这是在我的工作计算机上,它的工作原理 . 我知道你们中的一些人可能拥有更多限制性权利,但无论如何都要试一试;)搜索Google以获取有关ROBOCOPY参数的解释 .

    干杯!

  • 0

    7daysclean.cmd的这一修改如何考虑闰年?

    它可以在不到10行编码中完成!

    set /a Leap=0
    if (Month GEQ 2 and ((Years%4 EQL 0 and Years%100 NEQ 0) or Years%400 EQL 0)) set /a Leap=day
    set /a Months=!_months!+Leap
    

    Edit by Mofi:

    由于语法无效,J.R.贡献的上述条件总是评估为 false .

    并且 Month GEQ 2 也是错误的,因为在闰年中仅需要在3月到12月期间再添加86400秒,而不是2月份 .

    Jay发布的批处理文件 7daysclean.cmd 中,将闰日考虑在内的工作代码(仅在当前年度)将是:

    set "LeapDaySecs=0"
    if %Month% LEQ 2 goto CalcMonths
    set /a "LeapRule=Years%%4"
    if %LeapRule% NEQ 0 goto CalcMonths
    rem The other 2 rules can be ignored up to year 2100.
    set /A "LeapDaySecs=day"
    :CalcMonths
    set /a Months=!_months!+LeapDaySecs
    
  • 5

    这并不奇怪,但我今天需要做这样的事情并按计划任务运行它等 .

    批处理文件,下面的DelFilesOlderThanNDays.bat示例exec w / params:

    DelFilesOlderThanNDays.bat 7 C:\ dir1 \ dir2 \ dir3 \ logs * .log

    echo off
    cls
    Echo(
    SET keepDD=%1
    SET logPath=%2 :: example C:\dir1\dir2\dir3\logs
    SET logFileExt=%3
    SET check=0
    IF [%3] EQU [] SET logFileExt=*.log & echo: file extention not specified (default set to "*.log")
    IF [%2] EQU [] echo: file directory no specified (a required parameter), exiting! & EXIT /B 
    IF [%1] EQU [] echo: number of days not specified? :)
    echo(
    echo: in path [ %logPath% ]
    echo: finding all files like [ %logFileExt% ]
    echo: older than [ %keepDD% ] days
    echo(
    ::
    ::
    :: LOG
    echo:  >> c:\trimLogFiles\logBat\log.txt
    echo: executed on %DATE% %TIME% >> c:\trimLogFiles\logBat\log.txt
    echo: ---------------------------------------------------------- >> c:\trimLogFiles\logBat\log.txt
    echo: in path [ %logPath% ] >> c:\trimLogFiles\logBat\log.txt
    echo: finding all files like [ %logFileExt% ] >> c:\trimLogFiles\logBat\log.txt
    echo: older than [ %keepDD% ] days >> c:\trimLogFiles\logBat\log.txt
    echo: ---------------------------------------------------------- >> c:\trimLogFiles\logBat\log.txt
    ::
    FORFILES /p %logPath% /s /m %logFileExt% /d -%keepDD% /c "cmd /c echo @path" >> c:\trimLogFiles\logBat\log.txt 2<&1
    IF %ERRORLEVEL% EQU 0 (
     FORFILES /p %logPath% /s /m %logFileExt% /d -%keepDD% /c "cmd /c echo @path"
    )
    ::
    ::
    :: LOG
    IF %ERRORLEVEL% EQU 0 (
     echo:  >> c:\trimLogFiles\logBat\log.txt
     echo: deleting files ... >> c:\trimLogFiles\logBat\log.txt
     echo:  >> c:\trimLogFiles\logBat\log.txt
     SET check=1
    )
    ::
    ::
    IF %check% EQU 1 (
     FORFILES /p %logPath% /s /m %logFileExt% /d -%keepDD% /c "cmd /c del @path"
    )
    ::
    :: RETURN & LOG
    ::
    IF %ERRORLEVEL% EQU 0 echo: deletion successfull! & echo: deletion successfull! >> c:\trimLogFiles\logBat\log.txt
    echo: ---------------------------------------------------------- >> c:\trimLogFiles\logBat\log.txt
    
  • 1

    天哪,已经有很多答案了 . 我发现一个简单方便的路由是使用 & 参数从单个Windows命令行指令按顺序执行两次ROBOCOP.EXE .

    ROBOCOPY.EXE SOURCE-DIR TARGET-DIR *.* /MOV /MINAGE:30 & ROBOCOPY.EXE SOURCE-DIR TARGET-DIR *.* /MOV /MINAGE:30 /PURGE
    

    在此示例中,它的工作原理是挑选所有超过30天的文件( . )并将它们移动到目标文件夹 . 第二个命令再次添加 PURGE 命令,这意味着删除目标文件夹中源文件夹中不存在的文件 . 基本上,第一个命令MOVES文件和第二个DELETES,因为在调用第二个命令时它们不再存在于源文件夹中 .

    查阅ROBOCOPY的文档并在测试时使用/ L开关 .

  • 972

    你可以把它拉下来 . 您可以查看this question,以获得更简单的示例 . 当你开始比较日期时,复杂性就来了 . 可能很容易判断日期是否更大,但如果您需要实际获得两个日期之间的差异,则需要考虑许多情况 .

    换句话说 - 不要试图发明这个,除非你真的不能使用第三方工具 .

  • 6

    扩展了aku的答案,我看到很多人都在询问UNC的路径 . 只需将unc路径映射到驱动器号就可以使forfiles满意 . 例如,可以在批处理文件中以编程方式完成驱动器的映射和取消映射 .

    net use Z: /delete
    net use Z: \\unc\path\to\my\folder
    forfiles /p Z: /s /m *.gz /D -7 /C "cmd /c del @path"
    

    这将删除扩展名为.gz且超过7天的所有文件 . 如果你想确保Z:在使用之前没有映射到任何其他东西,你可以做一些简单的事情

    net use Z: \\unc\path\to\my\folder
    if %errorlevel% equ 0 (
        forfiles /p Z: /s /m *.gz /D -7 /C "cmd /c del @path"
    ) else (
        echo "Z: is already in use, please use another drive letter!"
    )
    
  • 4

    运行以下commands

    ROBOCOPY C:\source C:\destination /mov /minage:7
    del C:\destination /q
    

    移动所有文件(使用/ mov,移动文件,然后删除它们而不是/ move,移动整个文件树点然后删除)通过robocopy到另一个位置,然后在该路径上执行删除命令,你就是全部好 .

    此外,如果您有一个包含大量数据的目录,您可以使用 /mir 开关

  • 6

    我的命令是

    forfiles -p "d:\logs" -s -m*.log -d-15 -c"cmd /c del @PATH\@FILE"
    

    @PATH - 在我的情况下只是路径,所以我不得不使用 @PATH\@FILE

    forfiles /? 也不适合我,但 forfiles (没有"?")工作正常 .

    我唯一的问题是:如何添加多个掩码(例如“.log | .bak”)?

    所有这些关于forfiles.exe我downloaded here(在win XP上)

    但是,如果您使用Windows服务器forfiles.exe应该已经存在,它与ftp版本不同 . 这就是我应该修改命令的原因 .

    对于Windows Server 2003,我使用此命令:

    forfiles -p "d:\Backup" -s -m *.log -d -15 -c "cmd /c del @PATH"
    
  • 70

    这个为我做了 . 它适用于日期,你可以减去想要的数量,以便追溯到时间:

    @echo off
    
    set m=%date:~-7,2%
    set /A m
    set dateYear=%date:~-4,4%
    set /A dateYear -= 2
    set DATE_DIR=%date:~-10,2%.%m%.%dateYear% 
    
    forfiles /p "C:\your\path\here\" /s /m *.* /d -%DATE_DIR% /c "cmd /c del @path /F"
    
    pause
    

    cmd /c del @path /F 中的 /F 强制删除特定文件,在某些情况下文件可以是只读的 .

    dateYear 是年变量,您可以根据自己的需要更改减法

  • 17

    我的脚本删除超过特定年份的文件:

    @REM _______ GENERATE A CMD TO DELETE FILES OLDER THAN A GIVEN YEAR
    @REM _______ (given in _olderthanyear variable)
    @REM _______ (you must LOCALIZE the script depending on the dir cmd console output)
    @REM _______ (we assume here the following line's format "11/06/2017  15:04            58 389 SpeechToText.zip")
    
    @set _targetdir=c:\temp
    @set _olderthanyear=2017
    
    @set _outfile1="%temp%\deleteoldfiles.1.tmp.txt"
    @set _outfile2="%temp%\deleteoldfiles.2.tmp.txt"
    
      @if not exist "%_targetdir%" (call :process_error 1 DIR_NOT_FOUND "%_targetdir%") & (goto :end)
    
    :main
      @dir /a-d-h-s /s /b %_targetdir%\*>%_outfile1%
      @for /F "tokens=*" %%F in ('type %_outfile1%') do @call :process_file_path "%%F" %_outfile2%
      @goto :end
    
    :end
      @rem ___ cleanup and exit
      @if exist %_outfile1% del %_outfile1%
      @if exist %_outfile2% del %_outfile2%
      @goto :eof
    
    :process_file_path %1 %2
      @rem ___ get date info of the %1 file path
      @dir %1 | find "/" | find ":" > %2
      @for /F "tokens=*" %%L in ('type %2') do @call :process_line "%%L" %1
      @goto :eof
    
    :process_line %1 %2
      @rem ___ generate a del command for each file older than %_olderthanyear%
      @set _var=%1
      @rem  LOCALIZE HERE (char-offset,string-length)
      @set _fileyear=%_var:~0,4%
      @set _fileyear=%_var:~7,4%
      @set _filepath=%2
      @if %_fileyear% LSS %_olderthanyear% echo @REM %_fileyear%
      @if %_fileyear% LSS %_olderthanyear% echo @del %_filepath%
      @goto :eof
    
    :process_error %1 %2
      @echo RC=%1 MSG=%2 %3
      @goto :eof
    
  • 11

    复制此代码并将其另存为DelOldFiles.vbs .

    仅在命令提示中使用:cscript DelOldFiles.vbs 15

    15表示删除过去15天以上的文件 .

    'copy from here
        Function DeleteOlderFiles(whichfolder)
           Dim fso, f, f1, fc, n, ThresholdDate
           Set fso = CreateObject("Scripting.FileSystemObject")
           Set f = fso.GetFolder(whichfolder)
           Set fc = f.Files
           Set objArgs = WScript.Arguments
           n = 0
           If objArgs.Count=0 Then
               howmuchdaysinpast = 0
           Else
               howmuchdaysinpast = -objArgs(0)
           End If
           ThresholdDate = DateAdd("d", howmuchdaysinpast, Date)   
           For Each f1 in fc
         If f1.DateLastModified<ThresholdDate Then
            Wscript.StdOut.WriteLine f1
            f1.Delete
            n = n + 1    
         End If
           Next
           Wscript.StdOut.WriteLine "Deleted " & n & " file(s)."
        End Function
    
        If Not WScript.FullName = WScript.Path & "\cscript.exe" Then
          WScript.Echo "USAGE ONLY IN COMMAND PROMPT: cscript DelOldFiles.vbs 15" & vbCrLf & "15 means to delete files older than 15 days in past."
          WScript.Quit 0   
        End If
    
        DeleteOlderFiles(".")
     'to here
    

相关问题