批处理文件删除指定日期之前的文件

16

我该如何创建一个批处理文件以删除早于指定日期的文件?

以下方法似乎无效;

:: --------DELOLD.BAT----------
@echo off
SET OLDERTHAN=%1
IF NOT DEFINED OLDERTHAN GOTO SYNTAX

for /f "tokens=2" %%i in ('date /t') do set thedate=%%i
type %1
pause
set mm=%thedate:~0,2%
set dd=%thedate:~3,2%
set yyyy=%thedate:~6,4%

set /A dd=%dd% - %OLDERTHAN%
set /A mm=%mm% + 0

if /I %dd% GTR 0 goto DONE
set /A mm=%mm% - 1
if /I %mm% GTR 0 goto ADJUSTDAY
set /A mm=12
set /A yyyy=%yyyy% - 1

:ADJUSTDAY
if %mm%==1 goto SET31
if %mm%==2 goto LEAPCHK
if %mm%==3 goto SET31
if %mm%==4 goto SET30
if %mm%==5 goto SET31
if %mm%==6 goto SET30
if %mm%==7 goto SET31
if %mm%==8 goto SET31
if %mm%==9 goto SET30
if %mm%==10 goto SET31
if %mm%==11 goto SET30
if %mm%==12 goto SET31

goto ERROR

:SET31
set /A dd=31 + %dd%
goto DONE

:SET30
set /A dd=30 + %dd%
goto DONE

:LEAPCHK
set /A tt=%yyyy% %% 4
if not %tt%==0 goto SET28
set /A tt=%yyyy% %% 100
if not %tt%==0 goto SET29
set /A tt=%yyyy% %% 400
if %tt%==0 goto SET29

:SET28
set /A dd=28 + %dd%
goto DONE

:SET29
set /A dd=29 + %dd%

:DONE
if /i %dd% LSS 10 set dd=0%dd%
if /I %mm% LSS 10 set mm=0%mm%
for %%i in (*.*) do (
set FileName=%%i
call :PROCESSFILE %%~ti
)

set mm=
set yyyy=
set dd=
set thedate=
goto EXIT

:SYNTAX
ECHO.
ECHO USAGE:
ECHO DELOLD X
ECHO   Where X is the number of days previous to Today.
ECHO.
ECHO EX: "DELOLD 5" Deletes files older than 5 days.
GOTO EXIT

:PROCESSFILE
set temp=%1
set fyyyy=20%temp:~6%
set fmm=%temp:~0,2%
set fdd=%temp:~3,2%
if /I %fyyyy% GTR 2069 set fyyyy=19%temp:~6%


:: ***************************************
:: * This is where the files are deleted *
:: * Change the ECHO command to DEL to   *
:: * delete. ECHO is used for test.      *
:: ***************************************
if /I %yyyy%/%mm%/%dd% GEQ %fyyyy%/%fmm%/%fdd% (
ECHO %FileName%
)

set temp=
set fyyyy=
set fmm=
set fdd=

:EXIT

:: ----------END-DELOLD.BAT-------------

这里发布了一种基于 .BAT 文件的新方法,仅使用内部 CMD.EXE 命令:https://dev59.com/PmHVa4cB1Zd3GeqPoqSp#9747065 - Aacini
我不同意这是一个重复的问题...它很相似但并不完全相同:删除早于给定日期的文件与早于N天的文件不同,使用第二个意味着在两个日期之间计算天数,这在批处理文件中并不容易。 - cbuchart
8个回答

10

如果你正在使用Windows Server和/或已经安装了Server Resource Kit,forfiles可能正是你要找的。

示例: 打印出所有180天前的文件名称。

forfiles /S /D -180 /C "cmd /C Echo @Path" >olderthan180days.txt

删除所有超过365天的PDF文件

forfiles /S /M *.pdf /D -365 /C "cmd /C Del @Path"

很棒的解决方案,正是我所需要的。 - LPChip

10

我使用这个脚本:

////////////////////////////////////////////////////////
// Deletes file older than a number of days 
// in the current directory
////////////////////////////////////////////////////////
// Usage: wscript DeleteOlderThan.js [#Days]
// By default, remove files older than 30 days
////////////////////////////////////////////////////////

function removeDays(date, nDays)
{
    var dateRet = date
    return dateRet.setDate(date.getDate() - nDays);
}

function addSlash(strPath)
{
    var c = strPath.substr(-1, 1);
    if( c !== '\\' && c !== '/' )
    {
        strPath += '\\';
    }
    return strPath;
}

// Read arguments
var nDays = WScript.Arguments(0) || 30;

// Create system objects
var fs = WScript.CreateObject("Scripting.FileSystemObject");
var shell = WScript.CreateObject("WScript.Shell");

// Retrieve current directory
var strDirectoryPath = addSlash(shell.CurrentDirectory);

// Compute date
var dateNow = new Date();
var dateTest = removeDays(dateNow, nDays);

// Iterate on files
var folder = fs.GetFolder(strDirectoryPath);
var files = folder.Files;

for( var it = new Enumerator(files); !it.atEnd(); it.moveNext() )
{
    var file = it.item();

    if( file.DateLastModified < dateTest)
    {
        file.Delete(true);
    }
}

我每天都使用以下命令:

wscript "C:\Program Files\Utils\DeletesOlderThan.js" 30

7
编辑:我解决了。

要删除所有早于给定日期的文件:

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"

删除所有最新的文件:

REM del_new.bat
REM usage: del_new MM-DD-YYYY
for /f "tokens=*" %%a IN ('xcopy *.* /d:%1 /L /I null') do if exist "%%~nxa" del "%%~nxa"

7

eJames: 我发现您的xcopy解决方案非常有效!我最喜欢的是,由于XCOPY参数的格式似乎与日期设置无关,因此它应该在除英语以外的Windows语言版本中也能正常工作。太棒了!;]

有一个改进点是预先创建FILES_TO_KEEP.TXT文件,以便如果没有文件符合保留条件,第二个XCOPY语句仍然可以继续执行删除操作(如果找不到FILES_TO_KEEP.TXT文件,则会失败)。以下是我的脚本(请注意,在此示例中,我将其更改为仅删除*.pdf文件,并更改了临时文件名称,以更确保不存在潜在冲突,以及清理临时文件后):

@echo off
SET OLDERTHAN=%1
IF NOT DEFINED OLDERTHAN GOTO SYNTAX

echo >> ~~~FILES_TO_KEEP.TXT~
for /f "tokens=*" %%a IN ('xcopy *.pdf /d:%1 /L /I null') do if exist %%~nxa echo %%~nxa >> ~~~FILES_TO_KEEP.TXT~
for /f "tokens=*" %%a IN ('xcopy *.pdf /L /I /EXCLUDE:~~~FILES_TO_KEEP.TXT~ null') do if exist "%%~nxa" del "%%~nxa"
del ~~~FILES_TO_KEEP.TXT~

GOTO END

:SYNTAX
ECHO.
ECHO USAGE:
ECHO DELOLD mm-dd-yyyy
ECHO   Where mm-dd-yyyy is the date prior to which you want to delete files.
ECHO.
ECHO EX: "DELOLD 10-17-2008" Deletes files older than October 17, 2008.
ECHO.
ECHO This should work on any language version of Windows, but has only been 
ECHO tested in English-US versions.
GOTO END

:END

1

我的解决方案适用于以下情况:

  • 你的系统上有touch实用程序(我有)
  • 或者你可以使用date命令暂时更改系统日期(这可能不是常见情况,但谁知道呢)

以下是思路:

  1. 在目标目录中创建一个信号文件(具有唯一名称),并且时间戳等于您的删除阈值时间。可以使用touch(接受所需时间戳作为参数)或通过使用date /T记住当前日期,使用date <param>更改系统日期来完成。

  2. 使用for /f %%I in ('dir /od')迭代按日期排序的所有文件,逐个进行删除。当遇到(并删除)信号文件后停止删除。


1
与这里的其他答案相比,这似乎是一种极其冒险的方法。 - Dan Bechard
@Dan 如果你指的是有可能会干扰信号文件的可能性,那么可以通过将(2)分为两个阶段来进行保护:2.1 运行上述循环并将删除命令与文件名回显到临时文件中以构建脚本;2.2 调用该临时文件,但仅在遇到信号文件时才这样做。否则,中止。无论如何,这种解决方案当然是一个权宜之计。 - atzz
1
我在想,如果您意外地错误地订购了文件,那么在到达您不想删除的信号文件之前,您可能会删除数千个文件。我不喜欢有一个信号文件,而是明确检查每个文件的时间戳,以确保您可以放心地删除它。我也不太理解您的方法如何处理子目录(不确定这是否是OP的要求,但对我来说是必需的)。 - Dan Bechard
1
@Dan 在我看来,文件排序不正确并不比输入错误的截止日期更危险,因为结果是一样的。子目录可以通过递归应用整个过程来处理。虽然我不确定为什么要在不断扩大的需求集中保持这种方法的可行性。如果在我控制下的PC上执行此操作,我只需获取GNU find的Win端口(例如来自UnxUtils),然后完成它。 :) - atzz
谢谢你的提示,我已经安装了Git Bash,它自带GNU find。;) - Dan Bechard

1

该网站现在正在出售中... - mdhansen
我已经更新了URL。 - Niklas J. MacDowall

0

他正在使用set /a。在DOS中这根本行不通。因此,他使用cmd,实际上这仍然是一个非常明智的选择(即使有些麻烦),因为它是除了WSH以外在每个Windows上都能使用的唯一方式。而且WSH也可以通过组策略进行锁定。 - Joey

-1

我不知道你是否可以使用.BAT文件和Windows自带的一些工具来完成这个任务,但是你肯定可以使用.js(JScript)或.vbs(VBScript)文件。你是在Windows下进行操作吗?如果是,那么Windows默认可以处理.js和.vbs文件,就像处理.bat文件一样。它们更加强大。

而且,如果你只针对Windows Server 2008,那么有PowerShell,它甚至更好(可下载到其他Windows版本)。


请见https://dev59.com/EHVD5IYBdhLWcg3wNY1Z#51069。 - Derek 朕會功夫
嗯...我没有给你那个踩的评价。但我认为这更像是一条评论而不是一个答案 - Derek 朕會功夫
@Derek - 哦,好的。抱歉。 :) - Vilx-

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接