4

i have a notepad.txt document that lists the files that need to be copied to the folder that holds the batch file. the files are located in several sub directories and with my code, it copies all of the files with specified name.

for /f "delims=" %%i in (testlist.txt) do echo |robocopy "%dir1%." "C:\temporary" "%%i.*" /s /ndl /njs /njh /nc /ts /ns

how do i set this up properly so it will search the most recent file, and copy only the file not the folder and subfolder?

CMDneubie
  • 43
  • 4

2 Answers2

1

How to get file's last modified date on Windows command line?

for %a in (MyFile.txt) do set FileDate=%~ta

Compare 2 dates in a Windows batch file

set "sdate1=%olddate:~-4%%olddate:~3,2%%olddate:~0,2%"
set "sdate2=%newdate:~-4%%newdate:~3,2%%newdate:~0,2%"
if %sdate1% GTR %sdate2% (goto there)  else echo here

So given that you can already read the file and do the copy, here is pseudo code of the logic I would write for putting it all together:

set oldTimeStamp = "1901-01-01" //so first comparison wins and doesn't throw a null error
for each filename in list.txt
   set newTimestamp = getTimeStamp(filename)
   if newTimeStamp > oldTimeStamp then set fileToCopy = filename
   set oldTimeStamp = newTimeStamp
next
doCopy(fileToCopy)

Basically loop through each filename and get the timestamp. Store the timestamp of the previous file and compare the new and old timestamps. If the current one is newer, save the filename to a variable that you will use to copy. At the end of the loop, fileToCopy should contain the name of the file with the most recent modified time.

Community
  • 1
  • 1
1

The following code snippet retrieves the most recent file and echos its path. Here the wmic command is used to get standardised locale-independent timestamps, which can immediately be compared as strings, so it is not necessary to convert them to numbers. So here it is:

@echo off
setlocal EnableExtensions EnableDelayedExpansion

set "RECENT=00000000000000.000000+000"
set "RECENTFILE="
for /F "usebackq eol=| delims=" %%L in ("testlist.txt") do (
    setlocal DisableDelayedExpansion
    set "CURRFILE=%%~fL"
    if exist "%%~fL" (
        setlocal EnableDelayedExpansion
        for /F "skip=1 tokens=1 delims= " %%T in ('
            wmic DATAFILE ^
            WHERE Name^="!CURRFILE:\=\\!" ^
            GET LastModified ^
            /FORMAT:TABLE
        ') do (
            for /F "delims=" %%S in ("%%T") do (
                if %%S GTR !RECENT! (
                    endlocal
                    endlocal
                    set "RECENT=%%S"
                    set "RECENTFILE=%%~fL"
                ) else (
                    endlocal
                    endlocal
                )
            )
        )
    ) else (
        endlocal
    )
)
if defined RECENTFILE (
    rem Perform your action here:
    echo(!RECENTFILE!
)

endlocal
exit /B

What happens:

  • there are two variables RECENT and RECENTFILE which hold the timestamp of and the path to most recent file, respectively;
  • the outer for /F loop walks through the items in the list file testlist.txt;
  • for each existing item, a wmic query is executed to get the last modify date, and its output is parsed by two nested for /F loops, each iterating once only; since wmic returns Unicode strings, a single for /F loop is not enough because it leaves some orphaned carriage-return characters, which may impact the remaining code, but a second loop removes them;
  • the retrieved file date is compared to the buffered one in RECENT, and if it is greater, meaning that the file is newer, it is stored in RECENT and the respective file path is stored in RECENTFILE;
  • if variable RECENTFILE is finally not defined, the list testlist.txt does not point to existing files, or it is empty;
  • the toggling of delayed expansion is necessary to avoid trouble with any special characters;

Besides the fact, that the wmic queries are worse in terms of performance compared to getting the timestamps using for (for instance for %F in ("*.*") do echo %~tF), the following restriction applies:

The , character must not occur in any of the listed file paths!

According to this answer, there is a way to overcome this, but then the ) character is disallowed: to replace the clause WHERE Name^="!CURRFILE:\=\\!" by WHERE ^(Name^="!CURRFILE:\=\\!"^) (the escaping ^ of the parenthesis is only required as the wmic command line is placed within a for /F set). So you can either have , or ) within a wmic command line, but not both of these characters.

Community
  • 1
  • 1
aschipfl
  • 33,626
  • 12
  • 54
  • 99