720

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

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

4

25 回答 25

1141

享受:

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

有关更多详细信息,请参阅forfiles文档

有关更多好东西,请参阅Windows XP 命令行的 AZ 索引

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

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

对于 Windows 7 和更新版本(包括 Windows 10):

语法发生了一些变化。因此更新的命令是:

forfiles /p "C:\what\ever" /s /m *.* /D -<number of days> /C "cmd /c del @path"
于 2008-09-09T01:18:27.380 回答
81

运行以下命令

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

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

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

于 2011-05-27T08:40:36.753 回答
28

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

所以文件实际上被删除了

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

epoch:我没有考虑时间,因为需要删除早于某个日期的文件,花费数小时/分钟将删除本应保留的文件。

局限性

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

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

我希望这有帮助。

于 2009-08-24T14:55:55.933 回答
23
forfiles /p "v:" /s /m *.* /d -3 /c "cmd /c del @path"

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

于 2011-06-08T07:46:04.857 回答
17

看看我对类似问题的回答

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"

这将删除早于给定日期的文件。我敢肯定它可以修改为从当前日期起 7 天返回。

更新:我注意到 HerbCSO 对上述脚本进行了改进。我建议改用他的版本

于 2009-08-24T15:11:15.987 回答
12

我的命令是

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 服务器,forfiles.exe 应该已经存在,并且它与 ftp 版本不同。这就是为什么我应该修改命令。

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

forfiles -p "d:\Backup" -s -m *.log -d -15 -c "cmd /c del @PATH"
于 2010-12-14T06:46:25.030 回答
11

对于 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"
于 2015-07-25T15:37:04.677 回答
10

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

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

Jay发布了7daysclean.cmd,其中包含用于命令行解释器cmd.exe的快速“日期到秒”解决方案。但它没有考虑闰年正确。JR发布了一个附加组件,将当年的闰日考虑在内,但忽略了自基准年以来的其他闰年,即自 1970 年以来。

自 20 年以来,我一直使用使用小型 C 函数创建一次的静态表(数组),以便在我用 C/C++ 编写的应用程序中的日期/时间转换函数中快速获取包括 1970 年 1 月 1 日以来的闰日在内的天数。

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

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

首先,表格:

  1. 自 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
    

    只有在 C/C++ 中使用无符号 32 位变量,即无符号长(或无符号整数)时,才能计算 2039 年到 2106 年的秒数,纪元从 1970 年 1 月 1 日开始。

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

  2. 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
    
  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 区域和语言设置。分配给环境变量的分隔符和标记顺序Day以及MonthYear第一个FOR循环中GetSeconds必须根据需要调整为本地日期/时间格式。

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

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

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 DisableDelayedExpansion
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=" %%# in ('dir /A-D-H-S /B /S "C:\Temp"') do (
    call :GetSeconds "%%~t#:0"
    set "FullFileName=%%#"
    setlocal EnableDelayedExpansion
    rem if !Seconds! LSS %LastWeek% del /F "!FullFileName!"
    if !Seconds! LEQ %LastWeek% (
        echo Delete "!FullFileName!"
    ) else (
        echo Keep   "!FullFileName!"
    )
    endlocal
)
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 not "%DateTime: AM=%" == "%DateTime%" (
    set "DateTime=%DateTime: AM=%"
) else if not "%DateTime: PM=%" == "%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%"  == "0" if not "%Month:~1%"  == "" set "Month=%Month:~1%"
if "%Day:~0,1%"    == "0" if not "%Day:~1%"    == "" set "Day=%Day:~1%"
if "%Hour:~0,1%"   == "0" if not "%Hour:~1%"   == "" set "Hour=%Hour:~1%"
if "%Minute:~0,1%" == "0" if not "%Minute:~1%" == "" set "Minute=%Minute:~1%"
if "%Second:~0,1%" == "0" if not "%Second:~1%" == "" 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 two 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 EnableExtensions DisableDelayedExpansion
call :GetSeconds "%DATE:~-10% %TIME%"
set /A "LastWeek=Seconds-7*86400"

for /F "delims=" %%# in ('dir /A-D-H-S /B /S "C:\Temp"') do (
    call :GetSeconds "%%~t#:0"
    set "FullFileName=%%#"
    setlocal EnableDelayedExpansion
    if !Seconds! LSS %LastWeek% del /F "!FullFileName!"
    endlocal
)
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%"  == "0" if not "%Month:~1%"  == "" set "Month=%Month:~1%"
if "%Day:~0,1%"    == "0" if not "%Day:~1%"    == "" set "Day=%Day:~1%"
if "%Hour:~0,1%"   == "0" if not "%Hour:~1%"   == "" set "Hour=%Hour:~1%"
if "%Minute:~0,1%" == "0" if not "%Minute:~1%" == "" set "Minute=%Minute:~1%"
if "%Second:~0,1%" == "0" if not "%Second:~1%" == "" 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 小时”的回答,其中包含有关文件时间的大量附加信息。

于 2015-02-08T15:13:11.533 回答
9

对于 Windows Server 2008 R2:

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

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

于 2012-04-27T22:41:04.387 回答
8

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

在 CMD 中的用法:cscript //nologo 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
于 2011-01-26T01:36:21.123 回答
7

使用文件。

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

我的版本(用于服务器 2000 - 注意开关后没有空格)-

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:\WINDOWS\system32

于 2011-11-14T14:56:03.840 回答
6

考虑到闰年,如何对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

莫菲编辑:

由于语法无效, JR提供的上述条件始终为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
于 2010-07-01T19:38:57.160 回答
6

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 文件,并清理子文件夹。

于 2013-04-26T10:57:48.070 回答
5

我可以为这个已经很有价值的线程添加一个不起眼的贡献吗?我发现其他解决方案可能会删除实际的错误文本,但忽略了表示我的应用程序失败的 %ERRORLEVEL% 。并且我合法地想要 %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||echo found success

使用 oneliner 返回 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&&EXIT /B 1||EXIT /B 0

在其他代码中间的批处理文件的上下文中,使用 oneliner 将 ERRORLEVEL 保持为零以便成功(ver > nul 重置 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

对于 SQL Server 代理 CmdExec 作业步骤,我选择了以下内容。我不知道这是否是一个错误,但步骤中的 CmdExec 只识别第一行代码:

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%
于 2015-04-02T18:58:30.410 回答
5

天哪,已经有很多答案了。我发现一个简单方便的方法是使用&参数从单个 Windows 命令行指令按顺序执行 ROBOCOPY.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 开关。

于 2018-03-16T13:33:56.510 回答
4

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

mkdir c:\temp\OldDirectoriesGoHere
robocopy c:\logs\SoManyDirectoriesToDelete\ c:\temp\OldDirectoriesGoHere\ /move /minage:7
rmdir /s /q c:\temp\OldDirectoriesGoHere
于 2010-12-08T00:56:02.620 回答
4

我认为e.James 的回答很好,因为它早在 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 以来的总天数(之后它返回负数年)。

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

于 2014-01-02T23:04:16.127 回答
4

ROBOCOPY非常适合我。最初建议我的伊曼。但是不要将文件/文件夹移动到临时目录然后删除临时文件夹的内容,而是将文件移动到垃圾箱!!!

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

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

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

这是在我的工作计算机上,它可以工作。我知道你们中的一些人可能有更多的限制性权利,但还是试试吧;)在谷歌搜索关于 ROBOCOPY 参数的解释。

干杯!

于 2016-08-15T15:29:17.110 回答
4

删除所有超过 3 天的文件

forfiles -p "C:\folder" -m *.* -d -3 -c "cmd  /c del /q @path"

删除超过 3 天的目录

forfiles -p "C:\folder" -d -3 -c "cmd  /c IF @isdir == TRUE rd /S /Q @path"
于 2021-02-24T01:56:55.080 回答
3

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

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

于 2008-09-09T14:24:49.830 回答
3

这没什么了不起的,但是我今天需要做这样的事情并将其作为计划任务等运行。

批处理文件 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
于 2013-12-19T00:01:20.220 回答
3

扩展 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!"
)
于 2014-03-14T10:05:30.180 回答
1

这个是为我做的。它适用于日期,您可以减去所需的年数以及时返回:

@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

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

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

于 2017-05-19T08:49:54.263 回答
1

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

@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
于 2017-07-14T23:47:10.803 回答
0

更灵活的方法是使用FileTimeFilterJS.bat

@echo off

::::::::::::::::::::::
set "_DIR=C:\Users\npocmaka\Downloads"
set "_DAYS=-5"
::::::::::::::::::::::

for /f "tokens=* delims=" %%# in ('FileTimeFilterJS.bat  "%_DIR%" -dd %_DAYS%') do (
    echo deleting  "%%~f#"
    echo del /q /f "%%~f#"
)

该脚本将允许您使用天、分钟、秒或小时等度量。选择天气以按创建、访问或修改时间过滤文件 列出某个日期之前或之后(或两个日期之间)的文件 选择是否显示文件或目录(或两者) 是否递归

于 2020-11-12T09:09:13.430 回答