How do I get the latest file from a list of files in a particular directory?
Solution 1
ls -t1 | head -n 1
The first will list all files ordered by access time, the latter select the first line.
Solution 2
In zsh, the latest file in the current directory is
a=(*(om[1]))
latest_file=$a[1]
cp -p $latest_file /other/directory
(Glob qualifiers rock, but unfortunately the result is still a list even if you only request one element, hence the temporary array a
.)
In other shells, if you know that your file names cannot contain newlines or unprintable characters, you can use ls
:
latest_file=$(ls -t | head -n 1)
cp -p "$latest_file" /other/directory
However, it seems that what you're really asking for is the list of files that are newer than a particular file. For this, you can use the -cnewer
builtin of find
to detect files whose content or metadata has changed more recently than some other files. Note that the way I invoke it here, find
also collects files in subdirectories.
find . -cnewer "$previous_latest_files" -exec sh -c 'cp -p "$@" "$0"' /other/directory {} +
The problem remains to detect the previous latest file… In fact, what matters is the date of the copy. So create a marker file when you do the copy.
find . -cnewer marker_file -exec sh -c 'cp -p "$@" "$0"' /other/directory {} +
touch marker_file
If the files remain in the target directory, then you can simply synchronize the two directories. Note that if you delete some old files from the target directory but they remain in the source directory, they'll be copied again with this method.
rsync -a . /other/directory/
Solution 3
If you're just copying files from one directory to another based on their modification times, you might consider rsync
. A very simple way to do the same might be:
rsync -t ./dir1/ ./dir2/
Or just to see what it would do add:
rsync -t --list-only ./dir1/ ./dir2/
As Gilles notes in a comment below there may be extenuating circumstances that obviate the use of the -t
option for you. But if you take anything away from this let it be that you can and should test for the results you desire and that rsync
's --list-only
option is a very simple means of doing so.
Also, maybe...
man rsync
Solution 4
If your actual objective is to move a bunch of files based on modification time and your system's version of find
supports the -newerXY
type of tests, you could do something like
find -type f -newermt "@$lasttime" -exec mv -t path/to/destination/ {} +
where $lasttime
is the file modification time that you saved previously, in seconds since epoch (e.g. as obtained from stat -c %Y yourfile
).
You could also use find -newer somefile
or find -newermm somefile
to compare the modification times to that of a reference file directly, instead of saving the reference file's timestamp in a variable.
To limit the selection to the current directory (exclude subdirectories) you can add -maxdepth 1
to the find
command.
Related videos on Youtube
![peterh](https://i.stack.imgur.com/BfUwH.jpg?s=256&g=1)
peterh
Truthful words are not beautiful; beautiful words are not truthful. (Lao Tze) The Last Question
Updated on September 18, 2022Comments
-
peterh almost 2 years
I need to get the latest file from a list of files in a particular directory.
When I run the script the first time I've copied the list of files in a particular directory to another directory.
From the second run I need to get the latest files from a list of files in same directory to copy those files into the other directory.
Here in the first run I'm capturing the last file's creation date into a variable, when the script runs a second time, files that are greater than the last file creation date in the first run; these files need to be copied to the other directory.
Please could anyone help me out to get the latest files?
-
Gilles 'SO- stop being evil' about 10 yearsCaveat: if files are deleted from
dir2
but notdir1
, they'll be copied again. The question doesn't have enough information to know whether it's an issue. -
mikeserv about 10 years@Gilles: True.
tar
might be leveraged in that case.rsync
itself also offers as many additional sync points as you could wish for. Still, there's certainly not enough data in the question to know that it is. I too often solve problems that aren't there - if I'm not causing them - but this time I didn't.