FORFILES date -after- (date calc in cmd file)

7
我想在cmd文件中使用FORFILES,以处理给定日期之后到“今天”的所有文件。我可以使用类似于forfiles /d +07/10/2013 /c "cmd /c echo @fname"的命令来处理7/10/13之后的所有内容,但我想要的是能够从“今天”开始向前计算90天的内容。
是否有办法在cmd文件中进行日期计算,以便让我指定“x天前的今天”并将其输入到FORFILES中?
我不想使用VBS(虽然我找到了一个在VBS中可行的代码片段),尽管我可以重新编写我的脚本以适用于Powershell,但理想情况下我想坚持使用cmd。
为了澄清,“-90”将找到90天之前的所有文件;“+90”将找到比今天新90天的所有文件(这基本上没有用,因为几乎不可能有写有未来日期的文件),而“+7/30/2013”将找到比7/30/2013更新的所有文件。 我要的是最后一个时间段,最好能够在CMD文件中传递一个数字变量,例如“在过去的x天内”,而不是像上面显示的硬编码日期。所以,我希望能够在cmd文件中计算该日期。

看看我在这里的答案。 - Endoro
批处理文件创建/运行/删除VBS脚本,然后运行forfiles命令,这种方法可行吗? - foxidrive
我想完全避免使用VBS,有几个原因,尽管我意识到这样做会削弱一种实现方式。 - Debra
Endoro,我觉得这个方法可以,但是我不确定是否理解了它。似乎您正在建立一个目录列表文件,然后删除早于日期范围的条目。是这样吗?在这种情况下,这实际上可能是可以的,因为我确实想要构建一个文件列表,然后将其提供给其他东西。如果我没有正确解析,请澄清一下,“它是如何工作的”。顺便说一句,我在发布这个问题之前认真搜索过答案! - Debra
2
可能是FORFILES少于4天的重复内容 - aschipfl
2个回答

9

这里提供了一个解决方案,用于解决forfiles的设计缺陷,涉及到/D +dd天,假设未来不会有任何项目被修改,该方案基于两个嵌套的forfiles循环,并依赖于forfiles在没有匹配到提供的搜索条件时设置ErrorLevel的事实。

rem Define minimum and maximum age in days here (0 means today):
set /A MINAGE=0, MAXAGE=90

set "MAXAGE=%MAXAGE:*-=%" & set "MINAGE=%MINAGE:*-=%" & set /A MAXINC=MAXAGE+1
> nul forfiles /D -%MINAGE% /C "cmd /C if @isdir==FALSE 2> nul forfiles /M @file /D -%MAXINC% || > con echo @fdate  @file"

外部的 forfiles 循环迭代至少与变量 MINAGE 指定的时间一样久的项目。内部的 forfiles 循环在最多接收到来自外部循环迭代文件 @file 一次时,如果该文件也至少与 MAXINC(等于 MAXAGE 加上 1)一样久,则返回相同的文件;如果不是,则 forfilesErrorLevel 设置为 1,然后由 || 运算符捕获,只有在 ErrorLevel 被设置为非零值时才执行以下命令,即 echoMINAGEMAXAGE 都不能是负数(命令 set "MAXAGE=%MAXAGE:*-=%"set "MINAGE=%MINAGE:*-=%" 在这种情况下删除减号)。中间变量 MAXINC 被引入,以便将由 MAXAGE 指定的年龄本身包含在返回的结果中。
重定向 > nul 防止外部的 forfiles 返回空行,而内部的 forfiles 返回符合其搜索条件的项目(因为我们只关心不符合条件的项目)。2> nul 防止内部的 forfiles 循环在违反其搜索条件时返回错误消息。> con 覆盖了 > nul,以便 echo 命令实际返回所需的项目。 if @isdir==FALSE 部分过滤掉目录,以便仅处理文件。如果要仅处理目录,请将 FALSE 更改为 TRUE;如果要同时处理两者,请完全删除它。

做得很好,解释得很好 :) 可能值得说明的是,第二/第三组命令可以防止负数。另外,“redired items”是什么?是必需的还是重定向的? - Jimadine
谢谢!我按照建议扩展了描述并修正了拼写错误。 - aschipfl
这个回答值得更多的赞美。非常好的回答和解释。 - Kelly Bang

2
在PowerShell中,您可以像这样操作:
$refdate = (Get-Date).AddDays(-90)
Get-ChildItem | Where-Object {
    $_.LastWriteTime -ge $refdate
} | Select-Object -Expand Name

我喜欢优美的PowerShell答案,但我一直在权衡是将整个过程作为cmd文件、调用PowerShell脚本的cmd文件还是PowerShell脚本。在找到FORFILES之后,我觉得它是理想的,直到我遇到了这个日期问题,因为我实际上正在构建一个没有扩展名的文件列表,它将进入一些其他命令。无论如何,感谢你提供这个漂亮的代码。 - Debra
如果没有您观察到的奇怪行为(我认为是设计缺陷),forfiles 可以提供可行的解决方案。然而,总体来说,CMD/批处理在处理日期方面表现糟糕,所以我建议直接使用 PowerShell。 - Ansgar Wiechers

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