Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Given a list of file names, how can I sort it by file modification time?

The resulting output needs to look exactly like the input with the exception that the data has been sorted accordingly.

Here is a sample of the input.

/jobs/crm/import/done/20140227-1359-0009.txt
/jobs/bridge/open-workitem/done/20140227-1359-0009.txt
/jobs/bridge/opened-workitem/done/20140227-1359-0009.txt
/jobs/bridge/update-workitem/done/20140227-1401-0001.txt
/jobs/bridge/update-workitem/done/20140227-1403-0001.txt
/jobs/tfs/import/done/20140227-1401-0001.txt
/jobs/tfs/import/done/20140227-1403-0001.txt
/jobs/tfs/open-workitem/done/20140227-1359-0009.txt
share|improve this question
    
Sort them by what? –  Hauke Laging Feb 27 at 17:31
1  
There exists a command called sort. –  devnull Feb 27 at 17:34
4  
Please show us an example input and desired output. DO you want to sort the names alphabetically or the files by modification date? –  terdon Feb 27 at 17:37
1  
To sort by name, just use sort. Time etc would be more complex and need a script. Nobody can suggest anything without more information though. –  Graeme Feb 27 at 18:26
1  
Should it be sorted based on the modification time stored in the filesystem, or the timestamp in the filename? Based on an earlier version of the question, I assume it's the file mtime, not the filename. –  Mikel Feb 27 at 20:46

4 Answers 4

up vote 3 down vote accepted

Assuming your input is small, and the file names don't contain spaces or other weird characters, you can just use ls.

ls -dt $(cat files)

$(cat files) puts the contents of files on the command line, and splits them on whitespace to get a list of arguments. ls -t takes a list of files as its arguments, sorts them by mtime, and prints them. -d is needed so it lists directories using their name, rather than their contents.

If that's not sufficient, you can try the decorate/sort/undecorate pattern, e.g.

$ while IFS=$'\n' read file; do
    printf '%d %s\n' "$(stat -c +%Y "$file")" "$file"
  done <files | sort -k1nr | cut -f 2- -d ' ' >files.sorted

where IFS=$'\n' read file; do ... done <files sets file to each newline-delimited entry in files in turn, printf...stat... turns <filename> into <mtime> <filename>, sort -k1nr sorts lines based on the first field in reverse numeric order, then cut removes the <mtime>, leaving you with just <filename>s in sorted order.

share|improve this answer

Perl has the '-M' operator for a file modification date.

This oneliner sorts files like required. The first line from top is the youngest file:

perl -e 'map { print "$_\n"; } sort { -M $a <=> -M $b } <*>'

or with a file list

perl -e 'map { print "$_\n"; } sort { -M $a <=> -M $b } @ARGV' $(cat files)
share|improve this answer
    
Very nice, +1! The one with the file list breaks on files with spaces though. –  terdon Feb 28 at 2:18

Lets say your third party program is called producer.sh

then the following command will sort the files datetime part.

producer.sh | sed -e 's#/\([0-9].*$\)# \1#' |sort -i -k2|sed -e 's# #/#'

for reverse order

producer.sh | sed -e 's#/\([0-9].*$\)# \1#' |sort -r -i -k2|sed -e 's# #/#'

With your input, it produces

$ cat flist1 |sed -e 's#/\([0-9].*$\)# \1#' |sort -i -k2|sed -e 's# #/#'
/jobs/bridge/opened-workitem/done/20140227-1359-0009.txt
/jobs/bridge/open-workitem/done/20140227-1359-0009.txt
/jobs/crm/import/done/20140227-1359-0009.txt
/jobs/tfs/open-workitem/done/20140227-1359-0009.txt
/jobs/bridge/update-workitem/done/20140227-1401-0001.txt
/jobs/tfs/import/done/20140227-1401-0001.txt
/jobs/bridge/update-workitem/done/20140227-1403-0001.txt
/jobs/tfs/import/done/20140227-1403-0001.txt
share|improve this answer

Assuming your input text stream consists of either fully qualified path names of files, or simply files in the same directory you issue the command, you can use the ls command with a couple of parameters to get the lastest timestamped files first by using the command ls where (listoffiles is the input):

$ cat listoffiles | ls -lt

In order to sort the listoffiles by size (5th column of ls -lt output and largest size first) instead of timestamp, the following command will suffice:

$ cat listoffiles | ls -lt | sort -rn -k5

Note1: Just leave out the -rn parameter to get smallest size first

Note2: If the files are in the same directory, you can eliminate the preceding cat command in both of the above examples.

In order to separate all of the columns from the fully qualified path names of the listoffiles, I personally would use an nawk command to print out the column list of files in latest first timestamp order as follows:

$ cat listoffiles | ls -lt | nawk '{print $9}'
share|improve this answer
1  
Hi and welcome to the site. It is generally expected that you actually test your answers before posting. Had you done so, you would have realized that ls cannot take piped input (what would be the point?) and that this answer does not work in the slightest. Also, even if ls could accept piped input, your solutions would fail as on files containing white space or even on slightly different locales (think of how the date is displayed). –  terdon Feb 27 at 18:40
1  
btw, we don't use BB tags as forums but markdown –  Braiam Feb 27 at 18:41

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.