forfiles /D +12/1/%2 /C "cmd /c if /I @FDATE LEQ 12/31/%2 move @file %3\Archive\12-%2 >NUL"
forfiles应该定位2015年12月1日至2015年12月31日期间(包括第1期和第31期)的最后修改日期的所有文件,并将其移至归档。由于原因未知,最近修改日期为2015年12月3日和2015年12月9日的某些文件未被移动。此外,未移动上次修改日期为2015年12月4日至2015年12月8日的所有文件。
调试步骤: 处理了不同的月份:1月,2月等,Archiving成功了。 权限已经过检查和验证。 手动存档未移动的文件。 创建了未移动文件的副本,但仍然遇到相同的问题。我做的最后一件事是替换
if /I @FDATE LEQ 12/31/%2 move @file %3\Archive\12-%2 >NUL
与
echo @FDATE
确保所有修改日期都可见。可以看到未成功移动和存档的文件的修改日期。
答案 0 :(得分:0)
正如@JosefZ已经在his comment中指出的那样,if
无法比较日期值。
但是,要在修改日期过滤某个范围的文件,您可以使用两个嵌套的forfiles
循环:
> nul 2>&1 forfiles /D +01-12-2015 /C "forfiles forfiles /M @file /D -31-12-2105 /C 0x22cmd /C if 00x7840isdir==FALSE > con echo 00x7840fdate 00x7840file0x22"
两个嵌套forfiles
循环的外部循环枚举具有修改日期范围的给定下限的项目(按照(短)日期格式,日期以dd-MM-yyyy
格式给出我的系统;查看forfiles /?
的帮助文本,找出适合您系统的格式):
forfiles /D +01-12-2015
返回2015年12月1日或之后修改的所有项目。
然后,内部循环仅用于返回2015年12月31日或之前修改过的项目。为此,我们需要根据以下内容创建命令行:
forfiles /M * /D -31-12-2015 /C "cmd /C echo @fdate @file"
/M
之后的掩码需要设置为外部循环返回的@file
值,因此内部循环仅在外部循环的每次迭代中迭代一次;所以内循环只是简单地过滤外部循环所接收的每一个项目的修改日期。不需要指定/P
之后的位置,因为外循环已经从当前迭代项所在的目录执行内循环(或者通常是/C
之后的命令)(这也是真的)如果提供/S
开关也处理子目录。)
现在的挑战是从外部循环中隐藏内部循环的@file
等变量。诀窍是使用forfiles
的十六进制代码替换功能;例如,0x20
将替换为空格,0x22
替换为引号,0x40
替换为@
- 符号,0x78
是字母{{ 1}}。由于这个替换甚至在替换x
- 变量之前完成,我们需要声明@
以隐藏外部循环中的00x7840
符号,从而避免替换{{1}例如,因为@
将变为@file
,所以内循环接收@
,它将被转换回0x40
,然后立即被其值替换。
所以带有嵌套0x40file
循环的命令行可能如下所示:
@file
要过滤目录并仅返回文件,您需要检查forfiles
:
forfiles /D +01-12-2015 /C "forfiles forfiles /M @file /D -31-12-2105 /C 0x22cmd /C echo 00x7840fdate 00x7840file0x22"
最后,为避免@isdir
返回空行或错误消息,请使用重定向:
forfiles /D +01-12-2015 /C "forfiles forfiles /M @file /D -31-12-2105 /C 0x22cmd /C if 00x7840isdir==FALSE echo 00x7840fdate 00x7840file0x22"
另请参阅以下帖子:
答案 1 :(得分:0)
命令行if
无法比较日期值。例如,请参阅March 30, 2016
和April 10, 2016
之间的日期间隔中的错误结果(即根据我的Windows区域设置,在30.3.2016
和10.4.2016
之间):
==> forfiles /D +30.3.2016 /C "cmd /c if @FDATE leq 10.4.2016 (echo @fdate yes @file) else ( echo @fdate NOO @file)"
31.03.2016 NOO "file36322183.txt"
12.04.2016 NOO "inputs.bat"
03.04.2016 yes "mycharmap.bat"
09.04.2016 yes "SO"
12.04.2016 NOO "ttt.txt"
==>
切换到powershell似乎没有嵌套forfiles
那么麻烦:
==> forfiles /D +30.3.2016 /C "powershell -command if ('@FDATE'.ToDateTime([Globalization.CultureInfo]::CurrentCulture) -le '10.4.2016'.ToDateTime([Globalization.CultureInfo]::CurrentCulture)) { echo '@fdate yes @file'} else { echo '@fdate NOO @file'}"
31.03.2016 yes file36322183.txt
12.04.2016 NOO inputs.bat
03.04.2016 yes mycharmap.bat
09.04.2016 yes SO
12.04.2016 NOO ttt.txt
==>
Powershell命令可以提供正确的结果。不过,我也会测试@isdir
属性(请参阅上面两个列表中的SO
文件夹)。
答案 2 :(得分:0)
这是我最终要做的工作:
SET Backups=C:\Users\%username%\Documents\Backups
forfiles /P %Backups%\Backups--Cisco_Smartnet /m *.xls /D -90 /C
"cmd /c move @file %Backups%\Backups--Cisco_Smartnet\Old_Backups--
3+_Months_Old
对我来说,这是将90天或更早(/ D -90)的电子表格(.xls)移动到旧备份文件夹。 @file是目录中符合此条件的任何文件。 %backups%变量对于此命令并不重要,只是在我做很多这些操作时节省了时间。 SET行是它自己的行。从Forfiles到最后都是它自己的路线。
我希望这有帮助,玩得开心!