【问题标题】:Batch: Copy files which last modification were 15 minutes before批处理:复制上次修改时间为 15 分钟前的文件
【发布时间】:2018-11-08 11:01:10
【问题描述】:

我有一个自动创建文件的文件夹,我需要每 5 分钟复制一次新文件(即最后一次修改是在过去 5 分钟内的文件)。

 :loop
for %a in (C:\test\*) do (
 set FileDate=%~ta
)
 timeout /t 300
 goto loop

这就是我找到获取文件日期的方式,但我不知道如何比较并在 5 分钟内获取当前日期。

(复制命令不是必须的,因为是通过SSH,这个问题已经解决了)。

【问题讨论】:

  • 5 或 15 分钟?

标签: windows batch-file time


【解决方案1】:

批量日期时间计算是一项非常繁琐的任务。

我建议使用 PowerShell(至少作为一种工具)

获取当前目录最近 5 分钟内创建的文件。
此 powershell 命令将输出类似 dir 的列表:

Get-ChildItem -Path 'X:\path'|Where-Object {((Get-Date) - $_.LastWriteTime).TotalMinutes -le 5}

要将其限制为仅全名,您可以附加管道

| Select-Object -ExpandProperty FullName

或简单地将命令括在括号中并附加 (...).FullName

(Get-ChildItem -Path 'X:\path'|Where-Object {((Get-Date) - $_.LastWriteTime).TotalMinutes -le 5}).FullName

批量包装

:: Q:\Test\2018\11\08\SO_53206386.cmd
@Echo off
for /f "usebackq delims=" %%A in (`
  powershell -Nop -C "(Get-ChildItem -Path 'X:\path' -File |Where-Object {((Get-Date) - $_.LastWriteTime).TotalMinutes -le 15}).FullName"
`) Do Echo %%A

此批次的示例输出(列表本身)

> SO_53206386.cmd
Q:\Test\2018\11\08\SO_53206386.cmd

-File 参数需要 PowerShell v3+,但可以用另一个管道命令替换

| Where-Object {!($PSISContainer)}

过滤掉文件夹。 (反面是-Directory 或者没有! 不是)

@Echo off
for /f "usebackq delims=" %%A in (`
  powershell -Nop -C "(Get-ChildItem -Path 'X:\path' | Where-Object {!($PSISContainer)}| Where-Object {((Get-Date) - $_.LastWriteTime).TotalMinutes -le 15}).FullName"
`) Do Echo %%A

【讨论】:

  • 谢谢。我有点迷失了...首先,我必须做什么才能执行此命令,因为在 CMD 中我收到错误,它不被识别为内部或外部命令、程序或批处理文件可执行文件。
  • 第一行必须在powershell中执行或保存为.ps1文件,第二行保存为.bat/.cmd文件并执行。
  • 我还是迷路了...我只想执行 1 个文件(因为我每天都必须执行这个...)我必须安装一些东西吗?我可以在哪里写路径?..
  • 修改批次,更改X:\path以适应您的环境。
  • @Mofi 根据PS versions进行了一些编辑来解释powershell行为
【解决方案2】:

这是一个完全不同的解决方案,导致很可能出现相同的行为,其优点是文件的最后修改日期并不重要。因此,如果将文件复制到观察文件夹中,即使其最后修改时间不在最后 X 分钟内,也会对其进行处理。每次在文件夹中创建文件或文件被进程修改时,它都会自动使用 Windows 设置的存档文件属性。

@echo off
set "Folder=C:\test"
:loop
for /F "eol=| delims=" %%I in ('dir "%Folder%\*" /AA-D-H /B /ON 2^>nul') do (
    %SystemRoot%\System32\attrib.exe -a "%Folder%\%%I"
    echo Copy the file "%Folder%\%%I"
)
%SystemRoot%\System32\timeout.exe /T 300
goto loop

FOR 命令在后台以cmd.exe /C 启动的单独命令进程中执行以下命令行。

dir "C:\test\*" /AA-D-H /B /ON 2>nul

命令DIR输出

  • 因为/B,所以只有裸格式文件名和文件扩展名
  • 由于/AA-D-H,仅具有归档属性集的非隐藏文件
  • 因为/ON而按文件名排序(不是真的需要)
  • 在目录C:\test 中找到匹配通配符模式*

DIR 在找不到任何符合这些要求的目录条目时输出的错误消息通过将其从句柄 STDERR 重定向到设备 NUL 来抑制.

阅读有关Using Command Redirection Operators 的Microsoft 文章,了解2>nul 的解释。当 Windows 命令解释器在执行命令 FOR 在后台启动的单独命令进程中执行嵌入的dir 命令行。

DIR 在单独的命令过程中的输出被 FOR 捕获并逐行处理。

FOR 总是会跳过空行,但此处不会出现。

默认情况下,FOR 也会跳过以分号开头的行(文件名)。通过使用eol=| 将行尾字符从默认的; 更改为任何文件名都不能包含的竖线,可以禁用此行为。

FOR 默认使用空格/制表符作为分隔符分割子字符串(标记)中的行,并将第一个空格/制表符分隔的字符串分配给指定的循环变量I。此处不需要此行为,因为文件名可以包含一个或多个空格。出于这个原因,delims= 用于指定一个空的分隔符列表,从而禁用行拆分行为。

因此分配给循环变量I 是带有文件扩展名的文件名,由DIR 输出,没有路径。

命令ATTRIB 用于从当前文件中删除归档属性,以用于FOR 循环的下一次迭代。然后可以将文件复制到其他位置或进行处理,否则不会修改其内容。

要了解所使用的命令及其工作原理,请打开命令提示符窗口,在其中执行以下命令,并仔细阅读每个命令显示的所有帮助页面。

  • attrib /?
  • dir /?
  • echo /?
  • for /?
  • goto /?
  • timeout /?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-02
    • 1970-01-01
    • 2014-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多