Alex Rivera | Logout

Get the newest file based on timestamp

Asked 2010-08-16T17:25:42.637
11

My directory contains files in this format:

AA_20100806.dat
AA_20100807.dat
AA_20100808.dat
AA_20100809.dat
AA_20100810.dat
AA_20100811.dat
AA_20100812.dat

The filename includes a timestamp. i.e. [RANGE]_[YYYYMMDD].dat

I need to find out which file has the newest date using the timestamp on the filename not the system timestamp and store the filename in a variable and move it to another directory and move the rest to a different directory.

Edit
Report

4 Answers

27
ls | sort -n -t _ -k 2 | tail -1

assuming the [RANGE] portion could be anything:

  • Directory: /incoming/external/data
  • File format: [RANGE]_[YYYYMMDD].dat

Tools:

We don't need sed, since we can work with the entire output of ls command. Using ls, awk, sort, and tail we can get the correct file (check syntax against what your OS accepts):

NEWESTFILE=`ls | awk -F_ '{print $1 $2}' | sort -n -k 2,2 | tail -1`

Then it's just a matter of putting the underscore back in.

EDIT: I had a little time, so I got around to fixing the command, at least for Solaris.

Here's the convoluted first pass (this assumes that ALL files in the directory are in the same format: [RANGE]_[yyyymmdd].dat). I'm betting there are better ways to do this, but this works with my own test data (in fact, I found a better way just now; see below):

ls | awk -F_ '{print $1 " " $2}' | sort -n -k 2 | tail -1 | sed 's/ /_/'

... while writing this out, I discovered that you can just do this:

ls | sort -n -t _ -k 2 | tail -1

I'll break it down.

ls

gets the directory listing, just filenames. Now pipe that into the next command:

awk -F_ '{print $1 " " $2}'

awk allows you to take an input line and modify it. All I'm doing is specifying that awk should break the input wherever there is an underscore (_) with the -F

answered 2010-08-16T17:56:06.990
1
ls -1 AA* |sort -r|tail -1
answered 2010-08-16T17:40:55.960
1

Due to the naming convention of the files, alphabetical order is the same as date order. I'm pretty sure that in bash '*' expands out alphabetically (but can not find any evidence in the manual page), ls certainly does, so the file with the newest date, would be the last one alphabetically.

Therefore, in bash

mv $(ls | tail -1) first-directory
mv * second-directory

Should do the trick.

If you want to be more specific about the choice of file, then replace * with something else - for example AA_*.dat

answered 2010-08-17T08:29:24.150
1

My solution to this is similar to others, but a little simpler.

ls -tr | tail -1

What is actually does is to rely on ls to sort the output, then uses tail to get the last listed file name.

This solution will not work if the filename you require has a leading dot (e.g. .profile).

This solution does work if the file name contains a space.

answered 2012-03-27T09:31:07.820

Your Answer