79

I need to copy the newest file in a directory to a new location. So far I've found resources on the forfiles command, a date-related question here, and another related question. I'm just having a bit of trouble putting the pieces together! How do I copy the newest file in that directory to a new place?

double-beep
  • 5,031
  • 17
  • 33
  • 41
Devrin
  • 1,090
  • 1
  • 10
  • 11

10 Answers10

140

The accepted answer gives an example of using the newest file in a command and then exiting. If you need to do this in a bat file with other complex operations you can use the following to store the file name of the newest file in a variable:

FOR /F "delims=" %%I IN ('DIR "*.*" /A-D /B /O:D') DO SET "NewestFile=%%I"

Now you can reference %NewestFile% throughout the rest of your bat file.

For example here is what we use to get the latest version of a database .bak file from a directory, copy it to a server, and then restore the db:

:Variables
SET DatabaseBackupPath=\\virtualserver1\Database Backups

echo.
echo Restore WebServer Database
FOR /F "delims=|" %%I IN ('DIR "%DatabaseBackupPath%\WebServer\*.bak" /B /O:D') DO SET NewestFile=%%I
copy "%DatabaseBackupPath%\WebServer\%NewestFile%" "D:\"

sqlcmd -U <username> -P <password> -d master -Q ^
"RESTORE DATABASE [ExampleDatabaseName] ^
FROM  DISK = N'D:\%NewestFile%' ^
WITH  FILE = 1,  ^
MOVE N'Example_CS' TO N'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Example.mdf',  ^
MOVE N'Example_CS_log' TO N'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Example_1.LDF',  ^
NOUNLOAD,  STATS = 10"
Squashman
  • 13,649
  • 5
  • 27
  • 36
Chris Magnuson
  • 5,780
  • 7
  • 34
  • 37
  • 4
    Excellent...I was searching for how to get the most recent file, and the code example you give is the exact reason I'm searching for this, restoring a sql server backup! – tbone Aug 25 '09 at 21:09
  • 1
    This was helpful. Just a note to say, if your files are inconveniently in subdirectories (like mine are), you can use the '/S' flag in DIR to check recursively. i.e. insert '/S' after DIR above and it should work. –  Aug 01 '11 at 09:13
  • @ObligatoryMoniker : What is %%I? – Ashwin May 08 '12 at 08:26
  • How do I filter by Date only and not Date and Time? /O:D – DextrousDave Feb 03 '14 at 14:00
  • 1
    @Ashwin, %%I is the iterator in the FOR loop – CrazyTim May 15 '14 at 02:52
  • this is a much better answer than the accepted answer – FistOfFury Jun 07 '16 at 13:22
  • Nice answer. Explains properly. – Vaibhav Jain Oct 11 '18 at 06:43
  • Really nice Answer! Solved not only one problem, but all the work i had in the morning. Thanks a lot. I have created this Gist with my code to help others. Mine is a little different because it also uses rar extraction (Batch to Restore MSSQL Database after Extract the Backup from the newest .RaR synced from google Drive) https://gist.github.com/xxporkoxx/07c3f44c33bccff42196106d7ed78b1d – Diego Mello Oct 09 '22 at 18:33
72

Windows shell, one liner:

FOR /F "delims=" %%I IN ('DIR *.* /A-D /B /O:-D') DO COPY "%%I" <<NewDir>> & EXIT
Squashman
  • 13,649
  • 5
  • 27
  • 36
PabloG
  • 25,761
  • 10
  • 46
  • 59
  • 8
    Default delimiters are and so it is better to add "delims=" after FOR /F to accept filenames with spaces. Whole command will be FOR /F "delims=" %%I IN ('DIR *.* /B /O:-D') DO COPY %%I <> & EXIT – Cheburek Oct 13 '10 at 22:16
  • 1
    Note that the space in front of the & becomes part of the previous command. That has bitten me with SET, which happily puts trailing blanks into the value. – Chris Noe Mar 05 '11 at 19:15
  • 2
    @Ashwin: %%I is the value from `DIR *.* /B /O:-D` -- so for each iteration of the loop it is the filename. Since the loop exits on its first iteration, it's only value is the first file (with a dot in its name) in the directory. – idbrii May 24 '12 at 22:41
  • Hi All. How do I filter by Date only and not Date and Time? /O:-D – DextrousDave Feb 03 '14 at 14:00
  • If you're going to be using this on a batch of files. Save this in another cmd and call it via 'CMD /C ONE_LINER.CMD' – Luigi Aug 06 '15 at 13:22
  • 3
    @idbrii "(with a dot in its name)" < no because `*.*` in Windows has special behavior to match also files without dot, same as `*`. (Incidentally, even something like `*.*.*.*` does.) – CherryDT Jul 04 '21 at 09:56
11

To allow this to work with filenames using spaces, a modified version of the accepted answer is needed:

FOR /F "delims=" %%I IN ('DIR . /B /O:-D') DO COPY "%%I" <<NewDir>> & GOTO :END
:END
TimH - Codidact
  • 1,439
  • 1
  • 12
  • 13
7
@echo off
set source="C:\test case"
set target="C:\Users\Alexander\Desktop\random folder"

FOR /F "delims=" %%I IN ('DIR %source%\*.* /A:-D /O:-D /B') DO COPY %source%\"%%I" %target% & echo %%I & GOTO :END
:END
TIMEOUT 4

My attempt to copy the newest file from a folder

just set your source and target folders and it should work

This one ignores folders, concern itself only with files

Recommed that you choose filetype in the DIR path changing *.* to *.zip for example

TIMEOUT wont work on winXP I think

DoTheEvo
  • 874
  • 1
  • 9
  • 21
4

I know you asked for Windows but thought I'd add this anyway,in Unix/Linux you could do:

cp `ls -t1 | head -1` /somedir/

Which will list all files in the current directory sorted by modification time and then cp the most recent to /somedir/

Robert Swisher
  • 1,300
  • 11
  • 12
2

@Chris Noe

Note that the space in front of the & becomes part of the previous command. That has bitten me with SET, which happily puts trailing blanks into the value.

To get around the trailing-space being added to an environment variable, wrap the set command in parens.

E.g. FOR /F %%I IN ('DIR "*.*" /B /O:D') DO (SET NewestFile=%%I)

FutbolFan
  • 13,235
  • 3
  • 23
  • 35
Richard
  • 29
  • 2
  • Yes it works, but the standard way for `SET` is to use the quotes like `set "NewestFile=%%I"` – jeb Jun 29 '11 at 20:22
  • that might be your standard, but mine is parens... :-) – Richard Jul 05 '11 at 06:54
  • But parens fails for `(set var=&complex^)` quotes works `set "var=&complex^"` – jeb Jul 07 '11 at 12:48
  • and so it is. i can't recall the last time i did bitwise math in a BAT. I was perusing the set /? and it explicitly mentions quotes for that. I've been using parens for years. Don't really feel like cleaning up the files - I think I'll live with it. After all, I have both "if %1!==!" and "if [%1]==[]" formats and I've survived.... :-) – Richard Jul 20 '11 at 21:17
  • This exact expression fails for me, with "%%I was unexpected at this time" - Windows 10, all current updates. – RBerman Feb 04 '21 at 15:20
2

The previous answers compares the modification date and NOT the creation date. Here is an example of a script that compares based on the creation date and time:

set origFolderPath=..\Source\Customization.Solution
set distFolderPath=.\PublishCustomization.Solution

FOR /F "tokens=*" %%I IN ('DIR "%origFolderPath%\*.zip" /T:C /B /O:D') DO SET "NewestFile=%%I"
copy %origFolderPath%\%NewestFile%  %distFolderPath%

The trick is that /A-D that is used in previous answers checks the modification date which can be the same for all edited files if you run the script on grabbed files from a source control system like tfs and then a wrong answer will be yeilded. /T:C compares the creation date time instead which might be a solution in such cases.

YazanGhafir
  • 464
  • 3
  • 8
2

This will open a second cmd.exe window. If you want it to go away, replace the /K with /C.

Obviously, replace new_file_loc with whatever your new file location will be.

@echo off
for /F %%i in ('dir /B /O:-D *.txt') do (
    call :open "%%i"
    exit /B 0
)
:open
    start "window title" "cmd /K copy %~1 new_file_loc"
exit /B 0
moswald
  • 11,491
  • 7
  • 52
  • 78
0

Copy most recent files based on date from one directory to another directory

echo off
rem copying latest file with current date from one folder to another folder
cls
echo Copying files. Please wait...
:: echo Would you like to do a copy?
rem pause
for /f "tokens=1-4 delims=/ " %%i in ("%date%") do (
     set dow=%%i
     set month=%%j
     set day=%%k
     set year=%%l
)
:: Pad digits with leading zeros e.g Sample_01-01-21.csv
    set yy=%year:~-2%
:: Alternate way - set datestr=%date:~0,2%-%date:~3,2%-%date:~6,2%
set datestr=%day%-%month%-%yy%
:: echo "\\networkdrive\Test\Sample_%datestr%.csv"
rem copy files from src to dest e.g copy <src path> <dest path>
copy "D:\Source\Sample_%datestr%.csv" D:\Destination
echo Completed
rem pause

Save the above code with .bat file format and Change the directory as per your needs and run the batch file.

Bharathiraja
  • 714
  • 1
  • 12
  • 20
-2

Bash:

 find -type f -printf "%T@ %p \n" \
     | sort  \
     | tail -n 1  \
     | sed -r "s/^\S+\s//;s/\s*$//" \
     | xargs -iSTR cp STR newestfile

where "newestfile" will become the newestfile

alternatively, you could do newdir/STR or just newdir

Breakdown:

  1. list all files in {time} {file} format.
  2. sort them by time
  3. get the last one
  4. cut off the time, and whitespace from the start/end
  5. copy resulting value

Important

After running this once, the newest file will be whatever you just copied :p ( assuming they're both in the same search scope that is ). So you may have to adjust which filenumber you copy if you want this to work more than once.

Kent Fredric
  • 56,416
  • 14
  • 107
  • 150