last time file opened

Is it possible to get the time when file was opened last time and sort all files in a directory by those times?

Asked By: student


ls -ltu list all the files, showing and sorting by access time.

From man ls:

-u     with -lt: sort by, and show, access time with -l: show access
       time and sort by name otherwise: sort by access time
Answered By: Shawn J. Goff

This depends on exactly what you mean by "opened", but in general, yes. There are three timestamps normally recorded:

  • mtime — updated when the file contents change. This is the "default" file time in most cases.
  • ctime — updated when the file or its metadata (owner, permissions) change
  • atime — updated when the file is read

So, generally, what you want to see is the atime of a file. You can get that with stat or with ls. You can use ls -lu to do this, although I prefer to use ls -l --time=atime (which should be supported in almost all modern Linux distributions) because I don’t use it often, and when I do I can remember it better. And to sort by time, add the -t flag to ls. So there you go.

There is a big caveat, though. Updating the atime every time a file is read causes a lot of usually-unnecessary IO, slowing everything down. So, most Linux distributions now default to the noatime filesystem mount option, which basically kills atimes, or else relatime, which only updates atimes once a limit has passed (normally once per day) or if the file was actually modified since the previous read. You can find if these options are active by running the mount command.

Also, note that access times are by inode, not by filename, so if you have hardlinks, reading from one will update all names that refer to the same file.

And, be aware that c is not "creation"; creation isn’t tracked by Unix/Linux filesystems, which seems strange but actually makes sense because the filesystem has no way of knowing if it is the original — maybe the file was created forty years ago and copied here. And, in fact, many file editors work by making copies over the original. If you need that information, it’s best to use a version control system like git.

A little update, a decade later: some filesystems, like btrfs, include a fourth timestamp:

  • birth, or sometimes but not consistently, btime — this is explicitly a "file creation timestamp"

… at least, in the statx(2) system call man page. It seems to be pretty sparsely documented overall. It really suffers from the same problem that made it get left out in the first place: what exactly does it mean? Consider:

$ echo > foo; stat foo|grep Birth
 Birth: 2022-04-30 02:38:19.084919920 -0400
$ cp foo foo.tmp; mv foo.tmp foo; stat foo|grep Birth
 Birth: 2022-04-30 02:39:00.950269045 -0400

Here, I’ve created a file, and then copied it to a temporary file, and then moved that back. This changes the "birth" time. Is that right? Maybe! I’m not sure that’s really useful, at least not for humans. But anyway, for completeness: that’s a thing you might have available on a modern system.

Answered By: mattdm

If your listing is for human consumption, use ls with one of the date sorting flags (-tu for access (read) time, just -t for modification (write) time or -tc for inode change time). See mattdm’s answer for more information (in particular the caveat regarding -a and the definition of -c).

If this is for program consumption, parsing the output of ls is problematic. If your shell is zsh, you don’t need ls anyway: zsh has globbing qualifiers to sort the matches by increasing access (*(Oa)), inode change (*(Oc)) or modification (*(Om)) time. A lowercase o sorts by increasing age.

act_on_files_by_date *(Om)

Otherwise, if you know that the file names don’t contain any newline or non-printable characters (in the current locale), then you can do something like

ls -t | while read -r name; do act_on_one_file "$name"; done
ls -t | xargs -I {} act_on_one_file {}

If you want to invoke a command on many files at once, you need more setup. Note that act_on_files_by_date $(ls -t) doesn’t work just like this, as filenames containing wildcard characters or whitespace would be expanded in the result of the command substitution. The following code works as long as no filename contains a newline or a non-printable character:

set -f
act_on_files_by_date $(ls -t)
set +f
unset IFS

If you want to cope with arbitrary file names, you’ll have a very hard time without resorting to more powerful tools than a standard shell: zsh, perl, python…

The find command is best for this. See the -ctime, -mtime, and -atime options

Answered By: GBH

The following command sort the files according to their access time i.e. atime.

ls -lt --time atime
Answered By: vishy dewangan
Categories: Answers Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.