我正在寻找一种在批处理文件中删除所有早于7天的文件的方法。我在网上搜索过,并发现有些示例代码有数百行,而其他代码则需要安装额外的命令行工具来完成该任务。
在Bash中可以用几行代码完成类似的事情。看起来至少有点简单的东西可以在Windows的批处理文件中完成。我正在寻找在标准的Windows命令提示符中解决问题的解决方案,不需要任何额外的工具。请不要使用PowerShell或Cygwin。
我正在寻找一种在批处理文件中删除所有早于7天的文件的方法。我在网上搜索过,并发现有些示例代码有数百行,而其他代码则需要安装额外的命令行工具来完成该任务。
在Bash中可以用几行代码完成类似的事情。看起来至少有点简单的东西可以在Windows的批处理文件中完成。我正在寻找在标准的Windows命令提示符中解决问题的解决方案,不需要任何额外的工具。请不要使用PowerShell或Cygwin。
forfiles /P c:\sql_backups\ /S /M *.sql /D -90 /C "cmd /c del @PATH"
使用forfiles命令。
不同的版本有所不同。早期版本采用Unix风格参数。
我的版本(适用于Server 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目录中。
forfiles
中,通配符 *.*
并不匹配 所有 文件。它只匹配文件名中带有 .
的文件(即带有扩展名的文件)。原始问题并没有提到需要文件名中带有 .
。正确的参数是 /M *
,但这实际上已经是默认值了。根本不需要使用 /M
。 - AnT stands with Russia我认为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文件,并且也会清理子文件夹。
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
使用单行代码返回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
使用一行命令在批处理文件中保持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
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%
对于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
编辑人:Mofi
由J.R.提供的条件在语法无效的情况下始终为false。
而Month GEQ 2
也是错误的,因为只有在闰年3月到12月之间的那个月,才需要添加86400秒以获得更多一天的时间,而对于二月份则不需要。
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
哇,已经有很多答案了。我发现一种简单方便的方法是使用&参数在单个Windows命令行指令中连续执行ROBOCOPY.EXE两次。
ROBOCOPY.EXE SOURCE-DIR TARGET-DIR *.* /MOV /MINAGE:30 & ROBOCOPY.EXE SOURCE-DIR TARGET-DIR *.* /MOV /MINAGE:30 /PURGE
mkdir c:\temp\OldDirectoriesGoHere
robocopy c:\logs\SoManyDirectoriesToDelete\ c:\temp\OldDirectoriesGoHere\ /move /minage:7
rmdir /s /q c:\temp\OldDirectoriesGoHere
我认为e.James的回答很好,因为它可以在未经修改的Windows版本上使用,早至Windows 2000 SP4(可能更早),但它需要写入外部文件。这里是一个修改后的版本,它不会创建外部文本文件,同时保持兼容性:
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以来经过的天数(之后它会返回负数年份)。
注意:这种数学计算只能单向进行;无法从负输入中正确获取未来日期(它会尝试,但可能会超出该月的最后一天)。
在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"
这将删除7天前的所有扩展名为.gz的文件。如果您想在使用之前确保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!"
)
ROBOCOPY 对我来说非常有效。这是由我朋友 Iman 建议的。但是,不要将文件/文件夹移动到临时目录然后删除临时文件夹中的内容,而是将文件移到回收站!!!
以下是我的备份批处理文件的几行代码示例:
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