Windows 'dir' command: sort files by date when '/s' is specified

20,215

Solution 1

You can call out to Powershell from you batch file if you want to. This code can be shortened on newer versions of Powershell.

for /F "delims=" %%G IN ('powershell "gci -rec | where { ! $_.PSIsContainer } | sort LastWriteTime | select -last 1 | Select-Object fullname"') do set NewestFile=%%G

Full answer:

cd /d "K:\path\to\source\dir"
for /F "delims=" %%G IN ('powershell "gci -rec *.ext | where { ! $_.PSIsContainer } | sort LastWriteTime | select -last 1 | Select-Object fullname"') do set NewestFile=%%G
copy "%NewestFile%" "C:\path\to\dest\dir"

Solution 2

A simple solution could be

@echo off
    setlocal enableextensions disabledelayedexpansion

    set "root=K:\path\tp\source\dir"
    set "mask=*.ext"

    for %%r in ("%root%\.") do for /f "tokens=2,*" %%a in ('
        robocopy "%%~fr" "%%~fr" "%mask%" /njh /njs /nc /ns /ts /s /ndl /nocopy /is /r:0 /w:0 /l
        ^| sort /r 
        ^| cmd /v /e /c"(set /p .=&echo(!.!)"
    ') do set "lastFile=%%b"

    echo Last file : "%lastFile%"

This code uses robocopy to generate the list of files with a timestamp prefix (the switches just request no job header, no job summary, no file class, no file size, timestamp, recursive, no directory list, no directory information copy, include same files, no retry, no wait, don't copy only generate list).

This timestamp prefixed list (UTF yyyy/mm/dd hh:mm:ss last file write) is then sorted in reverse order to get the last file in the first line. This line is retrieved with a separate cmd instance (this avoids a time problem with a for /f reading long lists of data) so the for /f only reads one line.

As the robocopy lines contain the date, time and file name, to retrieve this last field, we request the for /f to retrieve two tokens: one containing the hour (will be stored in %%a) and the remaining text until the end of the line (stored in %%b)

The additional for %%r is included just to prevent a usual problem using robocopy. As we are quoting paths to prevent problems with spaces, we need to ensure the paths do not end with a backslash that will escape the path's closing quote and make the command fail.

Share:
20,215
alexleen
Author by

alexleen

I specialize in the conversion of caffeine into code.

Updated on July 09, 2022

Comments

  • alexleen
    alexleen almost 2 years

    Goal: I want to copy the latest file with a certain extension from a "source directory" to a "destination directory" using a batch file. The latest file may be under several sub-directories within the source directory.

    This question/answer is exactly what I want, however it does not seem to sort when the /s option is specified (as this comment would suggest):

    FOR /F "delims=|" %%I IN ('DIR "K:\path\tp\source\dir\*.ext" /B /S /O:D') DO SET NewestFile=%%I
    copy "%NewestFile%" "C:\path\to\destination\dir"
    

    You can test DIR "K:\path\tp\source\dir\*.ext" /B /S /O:D by itself to see that it does not sort.

    What I've Tried: This command by itself does work: DIR "K:\path\tp\source\dir\*.ext" /S /B | sort but I can't figure out how to use it in a for loop (batch file exits before I can determine the error - even with a pause at the end).

    Any ideas?

    See: dir docs

  • alexleen
    alexleen over 5 years
    This produces the same result. I believe the issue has to do with the dir command and not the for loop as you can run DIR "%MainDirectory%\%FileExtension%" /B /S /O:D by itself and observe incorrect sorting (or none at all).
  • alexleen
    alexleen over 5 years
    I edited your answer to include the full solution I ended up with - thanks!
  • Compo
    Compo over 5 years
    @alexleen, you may need to be very careful with this solution, I have a feeling that the returned filename may very easily become truncated and the file subsequently not copied
  • Squashman
    Squashman over 5 years
    To mitigate some of the long file path errors you could use the PUSHD command with your source directory. ROBOCOPY is the only program I know of that does not have issues with long file paths. ROBOCOPY will not help with finding the newest file without a lot if manipulation whether that be a batch file or Powershell.
  • Compo
    Compo over 5 years
    The paths don't need to be too long @Squashman, the potential issue isn't with the length as such but with the fixed column output you're returning which gets truncated.
  • John Kens
    John Kens over 5 years
    @alexleen Works fine for me over multiple OS's. I suggest looking into powershell.