批文件删除N天以前的文件
我正在寻找一种方法来删除MS-DOSbatch file中超过7天的所有文件。 我search了networking,发现了几百行代码的例子,还有一些需要安装额外命令行工具来完成任务的例子。
BASH中只需几行代码即可完成类似的工作 。 在Windows中,对于batch file来说,似乎至less可以轻松实现。 我正在寻找一个解决scheme,在标准的Windows命令提示符下工作,没有任何额外的实用程序。 请不要PowerShell或Cygwin。
请享用:
forfiles -p "C:\what\ever" -s -m *.* -d <number of days> -c "cmd /c del @path"
有关详细信息,请参阅文件文档 。
有关更多的好东西,请参阅Windows XP命令行的AZ索引 。
如果您的计算机上没有安装forfiles
,请将其从任何Windows Server 2003复制到位于%WinDir%\system32\
Windows XP计算机。 这是可能的,因为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"
运行以下命令 :
ROBOCOPY C:\source C:\destination /mov /minage:7 del C:\destination /q
移动所有的文件(使用/ mov,移动文件,然后删除它们,而不是/移动整个文件树,然后删除)通过robocopy到另一个位置,然后在该path执行删除命令,你们都是好。
另外如果你有一个有很多数据的目录,你可以使用/mir
开关
好吧,有点无聊,想出了这个,其中包含我的版本的穷人的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 /adhs /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
所以文件实际上被删除
二月 :硬编码到二十八天。 实际上,Bissextile的年代是一个地狱。 如果有人有一个想法,不会添加10行代码,继续发布,所以我把它添加到我的代码。
时代 :我没有考虑时间,因为需要删除比特定date更早的文件,花费几小时/分钟就会从一天中删除文件,这是为了保持。
局限性
时代认为你的短date格式是YYYY-MM-DD。 它需要适应其他设置或运行时评估(读取sShortTime,用户绑定configuration,在filter中configuration正确的字段顺序,并使用filter从参数中提取正确的数据)。
我提到我恨这个编辑器的自动格式? 它删除空行,复制粘贴是一个地狱。
我希望这有帮助。
看看我对类似问题的回答 :
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"
这会删除比给定date更早的文件。 我相信它可以修改为从当前date起七天。
更新:我注意到HerbCSO已经改进了上面的脚本。 我build议使用他的版本 。
forfiles /p "v:" /s /m *.* /d -3 /c "cmd /c del @path"
你应该/d -3
(3天前)这对我来说工作得很好。 所以所有复杂的批次都可以在垃圾桶里。 此外forfiles
不支持UNCpath,所以build立一个networking连接到一个特定的驱动器。
我的命令是
forfiles -p "d:\logs" -s -m*.log -d-15 -c"cmd /c del @PATH\@FILE"
@PATH
– 在我的情况只是path,所以我不得不使用@PATH\@FILE
也forfiles /?
不为我工作,但forfiles
(没有“?”)工作正常。
我唯一的问题是:如何添加多个掩码(例如“ .log | .bak”)?
所有这些关于我在这里下载的 forfiles.exe(在赢得XP)
但是,如果您使用Windows服务器forfiles.exe应该已经在那里,它不同于FTP版本。 这就是为什么我应该修改命令。
对于Windows Server 2003,我使用以下命令:
forfiles -p "d:\Backup" -s -m *.log -d -15 -c "cmd /c del @PATH"
对于Windows Server 2008 R2:
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天以前的文件。
'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
使用forfiles。
有不同的版本。 早期的人使用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
IMO,JavaScript正在逐渐成为一种通用的脚本标准:它可能比任何其他脚本语言(在Windows中都可以使用Windows脚本宿主)都有更多的产品可用。 我必须清除很多文件夹中的旧文件,所以这里有一个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文件,并清理子文件夹。
7daysclean.cmd上的这个修改考虑闰年怎么样?
它可以在less于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
编辑Mofi:
由于语法无效, JR以上条件所做的评估始终是错误的。
而Month GEQ 2
也是错误的,因为再增加86400秒的时间必须在三月到十二月的闰年内完成,而不是在二月份。
一个工作代码,考虑到闰日 – 仅在今年 – batch file7daysclean.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
batch file中经常会有相关的date/时间相关的问题需要解决。 但是命令行解释器cmd.exe没有用于date/时间计算的function。 许多使用附加控制台应用程序或脚本的良好工作解决scheme已经发布在Stack Overflow和其他网站的其他页面上。
基于date/时间的通用操作是将date/时间string转换为自确定date以来的秒数。 非常常见的是1970-01-01 00:00:00 UTC。 但是也可以使用任何一天,这取决于支持特定任务所需的date范围。
Jay发布了7daysclean.cmd,其中包含用于命令行解释程序cmd.exe的快速“date到秒”解决scheme。 但是,这并不需要考虑闰年。 JR公布了今年考虑闰日的附加值,但忽略了自基准年(即自1970年以来)的其他闰年。
我使用了20年的静态表(数组),使用小型C函数创build一次,以便快速获取包含在C / C ++编写的应用程序中date/时间转换函数中从1970-01-01开始的包括闰日在内的天数。
这个非常快速的表格方法也可以在使用FOR命令的批处理代码中使用。 所以我决定编写批处理子程序GetSeconds
,它计算自1970-01-01 00:00:00 UTC以来传递给此例程的date/时间string的秒数。
注意:由于Windows文件系统也不支持闰秒,所以不考虑闰秒。
首先,表格:
-
包括闰日在内的每年UTC 1970-01-01 00:00:00之间的天数。
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位variables(即无符号长整型(或无符号整型)),计算从1970-01-01开始的从2039年到2106年的秒数是唯一可能的。
但是cmd.exe用于mathexpression式的一个有符号的32位variables。 因此最大值是2147483647(0x7FFFFFFF),即2038-01-19 03:14:07。
-
闰年信息(不/是)1970年至2106年。
1970 - 1989: NNYNNNYNNNYNNNYNNNYN 1990 - 2009: NNYNNNYNNNYNNNYNNNYN 2010 - 2029: NNYNNNYNNNYNNNYNNNYN 2030 - 2049: NNYNNNYNNNYNNNYNNNYN 2050 - 2069: NNYNNNYNNNYNNNYNNNYN 2070 - 2089: NNYNNNYNNNYNNNYNNNYN 2090 - 2106: NNYNNNYNNNNNNNYNN ^ 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
使用这些表格将date转换为自1970-01-01以来的秒数非常简单。
请注意!
date和时间string的格式取决于Windows区域和语言设置。 如果需要,分隔符和分配给环境variablesDay
, Month
和Year
的令牌的顺序必须根据本地date/时间格式调整为GetSeconds
第一个FOR循环。
如果环境variablesDATE中的date格式与命令FOR %%~tF
所使用的date格式不同,则需要修改环境variables的datestring。
例如,当%DATE%
扩展到Sun 02/08/2015
而%%~tF
扩展到02/08/2015 07:38 PM
,下面的代码可以用于修改第4行:
call :GetSeconds "%DATE:~4% %TIME%"
这导致仅在2015年8月2日传递子例程 – 没有星期几缩写的3个字母和分隔空格字符的datestring。
或者,可以使用以下格式以正确的格式传递当前date:
call :GetSeconds "%DATE:~-10% %TIME%"
现在,来自datestring的最后10个字符被传递给函数GetSeconds
,因此,只要date和月份总是以预期顺序包含2位数字,即环境variablesDATE的datestring是否有星期GetSeconds
,即格式dd/mm/yyyy
或dd.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 /ADHS /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 ("YNNNYNNNYNNNYNNNYNNNY NNNYNNNYN") 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 ("NNYNNNYNNNYNNNYNNNYNN NYNNNYNN") 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开头的空格开始的行。
而且,数组也可以做得更小,也就是说,从1980-01-01 00:00:00到2038-01-19 03:14:07的时间范围可以减less,例如上面批量代码支持的时间范围就是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 /ADHS /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 ("NYNNN") 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上的date和时间格式以及文件时间比较的更多信息,请参阅我的答案。 查找batch file中的文件是否早于4小时,其中包含大量有关文件时间的附加信息。
我可以给这个已经很有价值的线索添加一个卑微的贡献。 我发现其他解决scheme可能会摆脱实际的错误文本,但忽略了%ERRORLEVEL%,这表示在我的应用程序中失败。 而且,只要它不是“找不到文件”错误,我就只需要%ERRORLEVEL%。
一些例子:
debugging和消除错误具体:
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
在其他代码(ver> nul重置ERRORLEVEL)的batch file的上下文中使用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&&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%
对于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"
我认为e.James的答案很好,因为它早在Windows 2000 SP4(可能更早)的未修改版本的Windows上工作,但它需要写入外部文件。 这是一个修改版本,它不会在创build外部文本文件的同时保持兼容性:
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)
为了真实地回答原来的问题,这里是一个脚本,如果你用天数作为参数来调用它,那么它就是所有的math运算。
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以来的总天数(之后它返回负数年份)。
注意:math只有一种方法; 它不能正确地从负面的input中获得未来的date(它会尝试,但可能会超过一个月的最后一天)。
你可以把这个关掉。 你可以看看这个问题 ,一个简单的例子。 当你开始比较date时,复杂性就来了。 可能很容易判断date是否大于date,但是如果需要真正获得两个date之间的差异,则需要考虑很多情况。
换句话说 – 不要试图发明这个,除非你真的不能使用第三方工具。
如果您拥有XP资源工具包,则可以使用robocopy将所有旧目录移动到一个目录中,然后使用rmdir删除该目录:
mkdir c:\temp\OldDirectoriesGoHere robocopy c:\logs\SoManyDirectoriesToDelete\ c:\temp\OldDirectoriesGoHere\ /move /minage:7 rmdir /s /qc:\temp\OldDirectoriesGoHere
这不是什么了不起,但我今天需要做这样的事情,并按计划执行任务等。
batch file,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
在aku的回答中,我看到很多人问UNCpath。 简单地将uncpath映射到驱动器盘符将使文件变得快乐。 例如,可以在batch file中以编程方式完成驱动器的映射和取消映射。
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!" )
你可能不会find一个完整的非安装解决scheme,而不是一个复杂的bat文件或windows脚本。 我使用delen ,把它放在一个系统目录下,然后像任何bat文件中的常规del命令一样使用它。
ROBOCOPY对我很好。 最初build议我的伊曼。 但是,而不是将文件/文件夹移动到临时目录,然后删除临时文件夹的内容,将文件移动到垃圾!
这是我的备份batch file的几行例如:
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天。 我使用variables,因为行可以很长,我可以重用他们的其他地点。 你只需要find与你的login相关的回收站的DOSpath。
这是在我的工作电脑上,它的工作原理。 I understand that some of you may have more restrictive rights but give it a try anyway;) Search Google for explanations on the ROBOCOPY parameters.
干杯!
This one did it for me. It works with a date and you can substract the wanted amount in years to go back in time:
@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
the /F
in the cmd /c del @path /F
forces the specific file to be deleted in some the cases the file can be read-only.
the dateYear
is the year Variable and there you can change the substract to your own needs
My script to delete files older than a specific year :
@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 /adhs /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