Search code examples
cmd

List files more recent than another file using Windows batch


dir /b 

lists the names of files in a directory. How do you list only the files more recent than a specified file, say foo.txt?


Solution

  • This batch file can be used for this task:

    @echo off
    if "%~1" == "" goto :EOF
    if not exist "%~1" goto :EOF
    if exist "%~1\" goto :EOF
    
    echo Files newer than %~nx1 in directory: %~dp1
    echo/
    
    for /F "eol=| delims=" %%I in ('dir "%~dp1" /A-D /B /O-D') do (
        if /I "%~nx1" == "%%I" goto ExitLoop
        echo %%I
    )
    
    :ExitLoop
    echo/
    pause
    

    The execution of the batch file is exited on batch file called

    • with no argument or
    • with an argument string which is not an existing file/directory or
    • with an argument string which is an existing directory instead of a file.

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

    DIR outputs line by line

    • just files because of /A-D (attribute not directory)
    • in bare format with file name + file extension only because of /B
    • ordered reverse by last modification/write date which means newest file first and oldest file last because of /O-D
    • all files including hidden files in the directory of specified file.

    FOR captures everything written to handle STDOUT of started background command process and then processes the captured lines line by line with skipping empty lines which do not exist here.

    FOR ignores by default lines starting with a semicolon. A file name can start with ;. For that reason the end of line character is redefined using option eol=| from default ; to vertical bar | as this character can't be used in a file name.

    FOR splits by default each line up into substrings using space and tab as delimiters and assigns just first space/tab separated string to specified loop variable I. For that reason the list of delimiters is redefined with option delims= to an empty list of delimiters resulting in disabling line splitting to process correct also file names containing one or more spaces.

    DIR outputs the file names sorted by date from newest to oldest. So inside the FOR loop a case-insensitive string comparison is used to check if the current file name is equal the specified file name. The loop is exited with a jump to a label below the loop if this condition becomes true. Otherwise the current file name is output to console.

    Finally the batch file pause the execution of the batch file to be able to read the list in case of having started the batch file by double clicking on it.

    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.

    • call /? ... explains the batch file argument references.
    • dir /?
    • echo /?
    • for /?
    • goto /?
    • if /?
    • pause /?

    Note: If one or more files have exactly the same last modification date of the specified file, it is unpredictable which of those files are also output by this code. One more IF condition would be necessary to exclude files with same file date as the specified file. The following IF condition can be used to exit the loop on file having same date/time after existing IF condition in body of FOR loop.

    for %%J in ("%~dp1%%I") do if "%%~tJ" == "%~t1" goto ExitLoop
    

    But this IF condition compares only file date/time without second. So it results also on exiting the loop if current file has same date, hour and minute, but a higher second value and is therefore also in real newer than the specified file on taking second into account which Windows command processor does not with this code.