简体   繁体   中英

Batch: Copy files which last modification were 15 minutes before

I have a folder where files are automatically created and I need every 5 minutes to copy the new files (that is, the files whose last modification was in the last 5 minutes).

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

That's the way I have found to get date of file but I don't know how to compare and get the current date less 5 minutes.

(The copy command is not necessary, because is via SSH and this problem is resolved).

In batch date time calculations are a very tedious task.

I suggest to use PowerShell (at least as a tool)

To get the files created in the current directory in the last 5 minutes.
This powershell command will output a dir -like listing:

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

To restrict this to only the FullName you can append the pipe

| Select-Object -ExpandProperty FullName

or simply enclose the command in parentheses and append (...).FullName

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

Wrapped in a batch

:: 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

Sample output of this batch (listing itself)

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

The -File parameter requires PowerShell v3+ but can be replaced with another piped command

| Where-Object {!($PSISContainer)}

filtering out folders. (The opposite is -Directory or no ! for not)

@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

Here is a completely different solution resulting in most likely the same behavior with the advantage that the last modification date of a file does not really matter. So if a file is copied into the observed folder, it is also processed even if its last modification time is not within the last X minutes. It uses the archive file attribute set by Windows automatically each time a file is created in a folder or the file is modified by a process.

@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

The command FOR executes the following command line in a separate command process started with cmd.exe /C in background.

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

The command DIR outputs

  • in bare format only file name and file extension because of /B
  • only non-hidden files with archive attribute set because of /AA-DH
  • ordered by file name because of /ON (not really needed)
  • found in directory C:\test matching wildcard pattern * .

The error message output by DIR on not finding any directory entry matching these requirements is suppressed by redirecting it from handle STDERR to device NUL .

Read the Microsoft article about Using Command Redirection Operators for an explanation of 2>nul . The redirection operator > must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded dir command line with using a separate command process started in background.

This output of DIR in separate command process is captured by FOR and processed line by line.

Empty lines are always skipped by FOR which do not occur here.

Lines (file names) starting with a semicolon are also skipped by default by FOR . This behavior is disabled by changing with eol=|the end of line character from default ; to vertical bar which no file name can have anywhere.

FOR splits up by default the line in substrings (tokens) using space/tab as delimiters and assigns just first space/tab delimited string to specified loop variable I . This behavior is not wanted here as file names can contain one or more spaces. For that reason delims= is used to specify an empty list of delimiters which disables the line splitting behavior.

So assigned to loop variable I is the file name with file extension as output by DIR without path.

The command ATTRIB is used to remove the archive attribute from current file for next iteration of the FOR loop. Then the file can be copied to a different location or processed otherwise not modifying its content.

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM