批量文件未能移动指定的文件

时间:2016-04-12 16:43:03

标签: batch-file last-modified modified-date

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

确保所有修改日期都可见。可以看到未成功移动和存档的文件的修改日期。

3 个答案:

答案 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, 2016April 10, 2016之间的日期间隔中的错误结果(即根据我的Windows区域设置,在30.3.201610.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到最后都是它自己的路线。

我希望这有帮助,玩得开心!