Ubuntu – Best way to list 100 first files in a directory sorted by time

filesystemls

What would be the best way to list 100 first files in a directory sorted by the created timestamp (oldest first). The directory is quite large (around 100000 files).

ls piped to head takes an awful long time to complete.

Edit:

  • Filesystem is ext3.
  • limiting the number of files in the folder is not worth the effort, since this is going to be a rare "clean-up" operation and files are generated by a 3rd party software.
  • Using file modified time, instead of the creation time provides and acceptable solution.

Best Answer

You say that "ls piped to head takes an awful long time to complete".

The cause of this is not ls, but the number of files in your directory. If you have 100,000 files in a single directory, any way of solving this problem would have to get information about all 100,000 files before it could even think about sorting them or printing any output.

If it's taking too long, the real solution is to split the files over multiple directories.

If you can't spread the files over several directories, is there any way you can narrow down the number of files to consider? e.g. if the file names include a date, maybe you can include a wildcard so the system doesn't have to sort 100,000 files. Or maybe they're sequentially numbered? (This may or may not help, but is worth trying.)

How many times are you trying to do this? Maybe it's worth saving/caching the output for re-use.


Now, a question.

Are you sure you mean "creation time" and not "change time"? Most tools can only display "change time", not "creation time".

Getting "creation time" is a very new thing, which requires an ext4 filesystem, and some tools that aren't easy to install.


If you want change time

Change time (ctime for short) means the time the attributes of the file last changed.

ls -c sorts by ctime.

You want the output in ascending order, not descending, so you need to reverse the output with the -r option too.

So you could do it like this:

ls -cr | head -n 100

A longer solution to the same problem using stat:

find . -mindepth 1 -maxdepth 1 -exec stat -c $'%Z\t%n' '{}' \; |
    sort -k 1n |
    cut -f 2 -d $'\t' |
    head -n 10 |
    sed -e 's/^\.\///'

but that runs slower than ls -cr on my system.


If you want modification time

Modification time (mtime for short) means the time the contents of the file last changed.

ls -t sorts by mtime.

Change ls -cr to ls -tr (best option) or change stat -c $'%Z\t%n' to stat -c $'%Y\t%n'.


If you need creation time

(crtime for short)

This is harder.

First, ensure the directory is on a filesystem that is formatted using ext4. You can use tune2fs -l <device name> to check this.

Then, there is a new stat format called %W, which can help you here. To get it, you'll have to download a version of GNU Coreutils released in October 2010 or after, extract it, compile it, and install it.

Then, depending on your kernel, this might work (haven't tried it).

find . -mindepth 1 -maxdepth 1 -exec stat -c $'%W\t%n' '{}' \; |
    sort -k 1n |
    cut -f 2 -d $'\t' |
    head -n 10 |
    sed -e 's/^\.\///'

See also:


If you get errors about "'$\t'

The '$\t' notation requires bash or zsh: it will not work in dash or sh on Ubuntu. If you really need to use those shells, you will need to change any \t to Ctrl+V, Tab and remove the leading $ from just before the opening quote.

Related Question