3

I have a directory with tens of thousands of files. I want to list the most recently modified files (for example files modified within the last day or whatever).

The following command works but is slow because it has to ls every file in the folder:

ls -rt | tail -n 10

The following command is faster but the output is not as detailed as ls:

find -mtime -1

Is there a way I can list the most recently modified files (either a set number or by date) with ls-like output but faster?

1
  • 1
    I removed the bash tag, as I didn't see anything bash-specific in your question. Different shells have different capabilities, so if bash is a hard requirement, please make that clear in the body of the question (along with the tag). Otherwise, shell would be appropriate.
    – Jeff Schaller
    Jul 22, 2019 at 16:12

2 Answers 2

5

At least the GNU and FreeBSD finds have the -ls action, which produces output similar to ls:

$ find . -ls
   392815      4 drwxr-xr-x   2 user  group      4096 Jul 22 18:39 .
   392816      0 -rw-r--r--   1 user  group         0 Jul 22 18:39 ./foo.txt
   392818      0 -rw-r--r--   1 user  group         0 Jul 22 18:39 ./bar.txt

GNU find also has very configurable output in the form of the -printf action.

That said, I do wonder what makes your ls so slow. Both find and ls need to read the whole directory and call lstat() on all the files to find the dates, so there shouldn't be much of a difference. ls does need to sort the whole list of files, so that could make a difference if there is a really large number of files. In that case, you might want to consider spreading the files out to different directories, possibly based on their date. Dropping the -r and use head instead of tail might help.

3

If you have the zsh shell available, it can do some of the date filtering and sorting for you:

list the two most recent files:

ls -ld -- *(om[1,2])

(add the D glob qualifier to also consider hidden files).

list the two oldest files (counting backwards from the end of the generated list):

ls -ld -- *(om[-2,-1])

Or:

ls -ld -- *(Om[1,2])

list the files that were modified more than 5 days ago:

ls -ld -- *(m+4)

(like for find -mtime +4 that's when the age rounded down to a number of days is strictly greater than 4).

list the files that were modified within the past 5 days:

ls -ld -- *(m-5)

These are all examples of "Glob Qualifiers". The zsh shell is doing all the hard work here; it comes up with the matching filenames (if any) and passes that list to ls for it to list out.

Note that if you want to limit the results to only plain files (not directories, sockets, pipes, etc), then use a .; for example:

list the plain files that were modified within the past 5 days:

ls -ld -- *(.m-5)
3
  • You may want to add . in the list of qualifiers, to be sure to only get regular files, e.g. *(.Om[1,2])
    – Kusalananda
    Jul 22, 2019 at 17:21
  • 1
    I had started to sprinkle them in, but then I thought "directories are files, too", and Stéphane edited them out. The question doesn't specify regular files in the prose or the examples, but it's a good qualifier to know about, regardless!
    – Jeff Schaller
    Jul 22, 2019 at 17:22
  • ... and you're using ls with -d anyway. Fair enough.
    – Kusalananda
    Jul 22, 2019 at 17:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .