关于windows:批处理文件,用于删除N天以前的文件

Batch file to delete files older than N days

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

在bash中,只需几行代码就可以完成类似的工作。对于Windows中的批处理文件,似乎至少可以做一些远程操作。我正在寻找一个在标准Windows命令提示符下工作的解决方案,不需要任何额外的实用程序。请不要使用PowerShell或Cygwin。


享受:

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

有关详细信息,请参阅文件文档。

有关更多好处,请参阅Windows XP命令行的A-Z索引。

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

默认情况下,Windows和Windows Server的较新版本安装了它。

对于Windows 7及更高版本(包括Windows 10):

语法有点变化。因此,更新后的命令是:

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


运行以下命令:

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

通过robocopy将所有文件(使用/mov,它移动文件,然后删除它们,而不是/move,它移动整个文件树,然后删除它们)移动到另一个位置,然后在该路径上执行一个删除命令,您就一切正常了。

另外,如果目录中包含大量数据,则可以使用/mir开关


OK有点无聊,想出了这个,它包含了我版本的一个穷人的linux epoch替代品,限制了日常使用(不保留时间):

第7天

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@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:这是检查文件的起始目录。

笔记

这是一个非破坏性代码,它将显示发生了什么。

变化:

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

类似于:

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

所以文件实际上会被删除

二月:硬编码为28天。真的,双性恋的岁月是一个地狱。如果有人有一个不想添加10行代码的想法,请继续发布,然后我将其添加到我的代码中。

epoch:我没有考虑时间,因为需要删除一个比某个日期早的文件,用小时/分钟就可以从一天中删除文件。

局限性

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

我有没有提到我讨厌这个编辑的自动格式化?它删除空白行,复制粘贴是一个地狱。

我希望这有帮助。


1
forfiles /p"v:" /s /m *.* /d -3 /c"cmd /c del @path"

你应该提前3天做手术,这样对我很好。所以所有复杂的批次都可能在垃圾桶里。另外,forfiles不支持UNC路径,因此请与特定驱动器建立网络连接。


看看我对类似问题的回答:

1
2
3
4
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"

这将删除早于给定日期的文件。我相信它可以被修改为从当前日期向后七天。

更新:我注意到Herbcso已经改进了上面的脚本。我建议用他的版本。


我的命令是

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

在我的例子中,@PATH只是一条路径,所以我不得不使用@PATH\@FILE

另外,forfiles /?也不为我工作,但forfiles没有"?"工作很好。

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

所有这些关于我在这里下载的forfiles.exe(在Win XP上)

但是,如果您使用的是Windows Server for files.exe,它应该已经存在,并且与ftp版本不同。这就是我应该修改命令的原因。

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

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

对于Windows Server 2008 R2:

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

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


复制此代码并将其保存为deloldfiles.vbs。

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

15表示删除过去超过15天的文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  '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

使用FordFrase.

有不同的版本。早期的使用Unix样式的参数。

我的版本(用于Server2000-注意开关后没有空格)-

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

要将forfiles添加到xp,请从ftp://ftp.microsoft.com/reskit/y2kfix/x86获取exe/

并将其添加到c:windowssystem32


使用批处理文件解决的问题通常与日期/时间相关。但是命令行解释器cmd.exe没有用于日期/时间计算的功能。许多使用其他控制台应用程序或脚本的好的工作解决方案已经发布在这里、堆栈溢出的其他页面和其他网站上。好的。

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

Jay发布了7dayscolean.cmd,其中包含命令行解释器cmd.exe的快速"从日期到秒"解决方案。但它没有考虑到闰年的正确性。J.R.发布了一个附加项,将当前年份的闰日考虑在内,但忽略了基准年以来的其他闰年,即1970年以来的其他闰年。好的。

我用20年的静态表(数组)创建了一个小C函数,用于快速获取包括在C/C++中的应用程序中的日期/时间转换函数的1970-01—01天的天数。好的。

这个非常快速的表方法也可以在批处理代码中使用for命令。因此,我决定对批处理子例程GetSeconds进行编码,它计算从1970-01-01 00:00:00 UTC以来传递给该例程的日期/时间字符串的秒数。好的。

注意:不考虑闰秒,因为Windows文件系统也不支持闰秒。好的。

首先,表格:好的。

  • 自1970-01-01 00:00:00 UTC起每年的天数,包括闰日。好的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    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

    使用1972~01-01的历元计算年份2039到2106的秒数,仅使用无符号32位变量,即C/C++中的无符号长(或无符号INT)即可。好的。

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

  • 1970年至2106年的闰年信息(否/是)。好的。

    1
    2
    3
    4
    5
    6
    7
    8
    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
  • 本年每月第一天的天数。好的。

    1
    2
    3
                       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以来的秒数。好的。

    请注意!好的。

    日期和时间字符串的格式取决于Windows区域和语言设置。如有必要,分配给环境变量DayMonthYearGetSeconds第一个for循环的定界符和令牌顺序必须适应本地日期/时间格式。好的。

    如果环境变量date中的日期格式与%%~tF上的命令使用的日期格式不同,则需要调整环境变量的日期字符串。好的。

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

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

    这会导致只传递到02/08/2015--日期字符串,没有工作日缩写的3个字母和分隔空格字符。好的。

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

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

    现在,从日期字符串开始的最后10个字符被传递给函数GetSeconds,因此环境变量date的日期字符串是带工作日还是不带工作日都不重要,只要day和month总是按预期的顺序有2个数字,即格式为dd/mm/yyyydd.mm.yyyy。好的。

    这里是批处理代码,其中包含解释注释,只输出要删除的文件和要保存在C:\Temp文件夹树中的文件,请参见第一个代码以获取循环。好的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    @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小时格式进行了优化。好的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    @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上的日期和时间格式以及文件时间比较的更多信息,请参阅我的回答,了解批处理文件中文件是否超过4小时,以及有关文件时间的更多信息。好的。好啊。


    对于Windows 2012 R2,以下功能可以工作:

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

    要查看将要删除的文件,请使用此

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


    在7dayscolean.cmd上考虑闰年的修改怎么样?

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

    1
    2
    3
    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

    Mofi编辑:

    由于语法无效,以上由J.R.提供的条件的计算结果始终为false。

    而且,Month GEQ 2也是错误的,因为在一个闰年中,必须在3月至12月的月份(而不是2月)再增加一天86400秒。

    jay发布的批处理文件7dayslean.cmd中考虑闰日(仅限本年度)的工作代码为:

    1
    2
    3
    4
    5
    6
    7
    8
    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

    在imo中,javascript逐渐成为一种通用的脚本标准:它可能比任何其他脚本语言在更多的产品中可用(在Windows中,它可以使用Windows脚本宿主)。我必须清除很多文件夹中的旧文件,所以这里有一个javascript函数可以做到:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    // 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);
        }
    }

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


    我可以对这条已经很有价值的线索再加一点谦虚的贡献吗?我发现其他解决方案可能会去掉实际的错误文本,但忽略了表示应用程序失败的%ErrorLevel%。我合法地想要%ErrorLevel%只要它不是"找不到文件"错误。

    一些例子:

    调试和消除错误:

    1
    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

    使用OneLiner返回错误级别成功或失败:

    1
    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

    使用OneLiner将错误级别保持为零,以便在批处理文件的上下文中在其他代码中成功(ver>nul重置错误级别):

    1
    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

    对于SQL Server代理的CmdExec作业步骤,我在下面登陆了。我不知道是不是bug,但步骤中的CmdExec只识别第一行代码:

    1
    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%


    我认为e.james的答案很好,因为它早在Windows2000 SP4(可能更早)就可以与未修改的Windows版本一起使用,但它需要写入外部文件。以下是在保持兼容性的同时不创建外部文本文件的修改版本:

    1
    2
    3
    4
    5
    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)

    为了符合最初的问题,这里有一个脚本,如果您使用天数作为参数调用它,它将为您进行所有的数学运算:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    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(之后返回负年份)以来的总天数。

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


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

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

    这并不是什么了不起的事情,但我今天需要做一些像这样的事情,并按计划的任务运行它,等等。

    批处理文件,delfilesolderthanndays.bat,下面带有示例exec w/params:

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    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

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

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

    在本例中,它的工作方式是选取所有超过30天的文件(.)并将其移动到目标文件夹。第二个命令与添加的purge命令相同,这意味着删除目标文件夹中不存在于源文件夹中的文件。因此,从本质上讲,第一个命令移动文件,第二个命令删除,因为当第二个命令被调用时,它们不再存在于源文件夹中。

    请查阅Robocopy的文档,并在测试时使用/L开关。


    在扩展AKU的答案时,我看到很多人询问有关UNC路径的问题。只需将UNC路径映射到驱动器盘符,就可以让forfiles满意。例如,驱动器的映射和取消映射可以在批处理文件中以编程方式完成。

    1
    2
    3
    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:未映射到任何其他对象,可以执行以下简单操作

    1
    2
    3
    4
    5
    6
    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!"
    )


    你也许能做到。你可以看一下这个问题,举个简单的例子。当你开始比较日期的时候,复杂性就来了。可能很容易判断日期是否更大,但如果您需要实际获得两个日期之间的差异,有许多情况需要考虑。

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


    Robocopy对我很有用。最初建议我的伊曼。但不要将文件/文件夹移动到临时目录,然后删除临时文件夹的内容,而是将文件移动到垃圾箱!!!!

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

    1
    2
    3
    4
    5
    6
    7
    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备份"文件夹中超过30天的内容。我使用变量是因为行可以变长,并且可以在其他位置重用它们。您只需要找到与登录相关联的回收站DOS路径。

    这是我的工作电脑,它能用。我知道你们中的一些人可能有更多的限制性权利,但还是要尝试一下;)在谷歌上搜索关于机器人模型参数的解释。

    干杯!


    这个是为我做的。它有一个日期,你可以用几年的时间来减去想要的金额,以便回到过去:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    @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是年份变量,您可以在这里根据自己的需要更改减法。


    删除特定年份以上文件的脚本:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    @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&nbsp;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