Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

How can I do a simple find which would order the results by most recently modified?

Here is the current find I am using (I am doing a shell escape in PHP, so that is the reasoning for the variables):

find '$dir' -name '$str'\* -print | head -10

How could I have this order the search by most recently modified? (Note I do not want it to sort 'after' the search, but rather find the results based on what was most recently modified.)

share|improve this question
    
github.com/shadkam/recentmost would do what is desired - but one needs to build it –  user3392225 Mar 7 at 13:50
add comment

migrated from stackoverflow.com Jun 7 '11 at 18:40

This question came from our site for professional and enthusiast programmers.

8 Answers

Try this very code find '$dir' -name '$str'\* -print | xargs ls -tl | head -10 but it's useful to filter data by -mmin/-mtime and -type

share|improve this answer
add comment

I don't think find has any options to modify the output ordering. -mtime and -mmin will let you restrict the results to files that have been modified within a certain time window, but the output won't be sorted -- you'll have to do that yourself. GNU find has a -printf option that, among other things, will let you print the modification time of each file found (format strings %t or %Tk) ; that might help you sort the find output the way you wish.

share|improve this answer
add comment

If you have GNU find, make it print the file modification times and sort by that. I assume there are no newlines in file names.

find . -type f -printf '%T@ %p\n' | sort -k 1nr | sed 's/^[^ ]* //' | head -n 10

If you have Perl (again, assuming no newlines in file names):

find . -type f -print |
perl -l -ne '
    $_{$_} = -M;  # store file age (mtime - now)
    END {
        $,="\n";
        @sorted = sort {$_{$a} <=> $_{$b}} keys %_;  # sort by increasing age
        print @sorted[0..9];
    }'

If you have Python (again, assuming no newlines in file names):

find . -type f -print |
python -c 'import os, sys; times = {}
for f in sys.stdin.readlines(): f = f[0:-1]; times[f] = os.stat(f).st_mtime
for f in (sorted(times.iterkeys(), key=lambda f:times[f]), reverse=True)[:10]: print f'

There's probably a way to do the same in PHP, but I don't know it.

If you want to work with only POSIX tools, it's rather more complicated; see How to list files sorted by modification date recursively (no stat command available!) (retatining the first 10 is the easy part).

share|improve this answer
    
I think the find version shows the oldest files, and that you need to add the -r option to sort. –  Quentin Pradet Sep 7 '12 at 6:56
add comment

You don't need to PHP or Python, just ls:

man ls:
-t     sort by modification time
-r,    reverse order while sorting (--reverse )
-1     list one file per line

find /wherever/your/files/hide -type f -exec ls -1rt "{}" +;

If command * exits with a failure status (ie Argument list too long), then you can iterate with find. Paraphrased from: The maximum length of arguments for a new process

  • find . -print0|xargs -0 command (optimizes speed, if find doesn't implement "-exec +" but knows "-print0")
  • find . -print|xargs command (if there's no white space in the arguments)

If the major part of the arguments consists of long, absolute or relative paths, then try to move your actions into the directory: cd /directory/with/long/path; command * And another quick fix may be to match fewer arguments: command [a-e]*; command [f-m]*; ...

share|improve this answer
1  
If there are a lot of files, this fails with 'Argument list too long' on the ls. –  occulus Sep 3 '12 at 8:41
    
That's true, but I believe the question was "how do I do a simple find..." –  Ярослав Рахматуллин Sep 3 '12 at 10:53
add comment

You do only need ls

You could do find /wherever/your/files/hide -type f -exec ls -1rt "{}" +; as stated above,

or

ls -1rt `find /wherever/your/file/hides -type f`
share|improve this answer
1  
If there are a lot of files, this fails with 'Argument list too long' on the ls. Maybe recook to use xargs? –  occulus Sep 3 '12 at 8:41
add comment

I found that this gets the job done on Mac OS X (and generic enough to work on other Unixen as well):

find . -type f -ls | awk '{print $(NF-3), $(NF-2), $(NF-1), $NF}' | sort
share|improve this answer
    
Sadly, this prints out localized month names on my Croatian setup, making sort incorrect. –  Ivan Vučica Apr 15 '13 at 20:19
add comment

Use this:

find . -printf "%T@ %Tc %p\n" | sort -n

printf arguments from man find:

  • %Tk: File's last modification time in the format specified by k.

  • @: seconds since Jan. 1, 1970, 00:00 GMT, with fractional part.

  • c: locale's date and time (Sat Nov 04 12:02:33 EST 1989).

  • %p: File's name.

share|improve this answer
1  
+1 Very useful, the first answer to this I have found with a readable/useful date output –  Jake N Jun 26 '13 at 13:48
add comment
find . -type f -mtime 0 -printf "[%TD %TI:%TM%Tp] %s %p\n" | sort -n | awk '{ 
    hum[1024**4]="TB"; hum[1024**3]="GB"; hum[1024**2]="MB"; hum[1024]="KB"; hum[0]="B"; 
    for (x=1024**4; x>=1024; x/=1024){ 
    if ($3>=x) { printf $1" "$2"\t%7.2f %s\t%s\n",$3/x,hum[x],$4;break }
    }}';

this command will sort files by modified date and display out like

[12/05/13 03:10PM] 1.75 MB ./file.text
[12/06/13 11:52PM] 2.90 MB ./file2.mp4
[12/07/13 04:11PM] 4.88 MB ./file3.mp4
[12/07/13 09:17PM] 4.74 MB ./test.apk
share|improve this answer
add comment

Your Answer

 
discard

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