Quick Links

When does "changed" not mean "modified"? When we're talking about Linux file timestamps. In this guide, we'll explain how the system updates them, and how to alter them yourself.

The Difference Between atime, mtime, and ctime

Every Linux file has three timestamps: the access timestamp (atime), the modified timestamp (mtime), and the changed timestamp (ctime).

The access timestamp is the last time a file was read. This means someone used a program to display the contents of the file or read some values from it. Nothing was edited or added to the file. The data was referenced but unchanged.

A modified timestamp signifies the last time the contents of a file were modified. A program or process either edited or manipulated the file. "Modified" means something inside the file was amended or deleted, or new data was added.

Changed timestamps aren't referring to changes made to the contents of a file. Rather, it's the time at which the metadata related to the file was changed. File permission changes, for example, will update the changed timestamp.

The standard ext4 Linux file system also allocates space for a file-creation timestamp in its internal file system structures, but this hasn't been implemented yet. Sometimes, this timestamp is populated, but you can't depend on the values in it.

The Anatomy of a Timestamp

Linux timestamps hold a number rather than a date and time. This number is the number of seconds since the Unix epoch, which was midnight (00:00:00) on January 1, 1970, in Coordinated Universal Time (UTC). Leap seconds are ignored in Linux timestamps, so they aren't analogous to real time.

When Linux needs to display a timestamp, it translates the number of seconds into a date and time. This makes it easier for humans to understand. The location and time zone the computer viewing the file is in guides the conversion of the number of seconds to a date and time. It also ensures the month is in the correct language.

So, how many seconds can be stored in a timestamp? A lot—2,147,483,647, to be precise. That's a big number, but is it enough? If you add that to the Unix epoch, and then translate it to a date and time, you get Tuesday, January 19, 2038, at 03:14:07 a.m. We'll need a different scheme for timestamps before then, though.

Viewing Timestamps

When you use the -l (long listing) option with ls, as shown below, you can see the modified timestamp:

ls -l dp.c

If you want to see the access timestamp, use the -lu (access time) option like so:

ls -lu dp.c

And finally, to see the change timestamp, you can use the -lc (change time) option; type the following:

ls -lc dp.c

ls -l dp.c in a terminal window

The timestamps above show the file's contents were last modified on April 21, 2019. The access and changed timestamps are identical because the file was copied from another computer to this one on January 20, 2020, and both timestamps were updated at that time.

To see all timestamps simultaneously, use the stat command as follows:

stat dp.c

stat dp.c in a terminal window

The time zones are listed at the bottom of the display. As you can see, they have a very accurate, fractional seconds component. At the end of each timestamp, you also see a -0500 or -0400 .

These are time zone offsets. The file system records the timestamps in UTC and converts them to the local time zone when displayed by stat. The computer we used to research this article is configured as if it were in the Eastern Standard Time (EST) zone of the U.S.

That time zone is five hours behind UTC when EST is in force. However, it's four hours behind UTC when Eastern Daylight Time (EDT) is in force. In April 2019, when the modified timestamp was changed, EDT was in effect. That's why two of the timestamps have a five-hour offset, but the modified has a four-hour offset.

The offsets and time zones aren't stored anywhere. There's neither an inode nor a file system space devoted to holding these values. You have to calculate these on the fly using the timestamp (which is always in UTC time), the local time zone of the computer displaying the file, and whether DST was in effect.

You also see a "Birth" timestamp, which is reserved for the creation date of the file. This is not implemented, and you see a hyphen "-" instead of a timestamp.

Changing Timestamps

If you want, you can change the timestamps on a file. You can use the touch command to change the access or modified timestamps, or both:

touch -a dp.c

To set a new access timestamp, you would use the -a (access time) option. This command sets the access timestamp to the computer's current time:

stat dp.c

touch -a dp.c in a terminal window

The access timestamp changed, as expected. However, the changed timestamp was updated as well; this is normal.

To change the modified timestamp, you can use the -m (modified time) option:

touch -m dp.c

stat dp.c

touch -m dp.c in a terminal window

This time, the modified and changed timestamps were updated.

You can use the -d (date) option if you want to change both the access and modified timestamps simultaneously. You can also specify a time and date—you're not restricted to changing the timestamps to the present.

We'll use the following command to set the access and modified timestamps to 10:30:45 on January 15, 2020:

touch -d "2020-01-15 10:30:45" dp.c

stat dp.c

touch -d "2020-01-15 10:30:45" dp.c in a terminal window

We've now set the access and modified timestamps to a date in the past. The changed timestamp was also updated to the current time of the computer.

You can also use the -r (reference) option, as shown below, if you want to set the timestamps of one file to the timestamp values of another:

touch dp.c -r dice_words.sl3

stat dp.c

touch dp.c -r dice_words.sl3 in a terminal window

And then, we're pretty much back where we started, with a mixture of -0400 and -0500 timestamps.

Let's do something that only affects the changed timestamp. We'll use the chmod command to give an executable file execute permissions for all users:

chmod +x dp

stat dp

The "chmod +x dp" and "stat dp" commands in a terminal window.

The changed timestamp was the only one that updated. This is because the file itself wasn't changed—it was neither accessed nor modified. However, the metadata about the file was changed.

How the File System Updates Timestamps

When a file system is mounted, there are options you can use to specify how that file system should operate or be treated. These are stored in the /etc/fstab file, which is read and processed at boot time. You can also set options to dictate the scheme they should use to update the access timestamp.

The following are some of the most common options:

  • strictatime (strict atime): This option updates the access timestamp of files every time they're accessed. There's an overhead attached with this approach, but some servers can benefit from this scheme. It has little merit on a desktop or laptop computer.
  • noatime (no atime): This option fully disables the access timestamps for files and directories from updating. The modified timestamps, however, will still update.
  • nodiratime (no dir atime): This option enables access timestamps for files to update, but disables it for directories.
  • relatime (relative atime): This option updates the access timestamp only if it was more than 24-hours old, or the previous one was older than the current modified or changed timestamps. This strikes a good balance between access timestamps updating too frequently or not updating at all.

Let's look at the /etc/fstab file for this computer and see which options are set:

less /etc/fstab

less /etc/fstab in a terminal window

The /etc/fstab file is displayed for us, as shown below.

The /etc/fstab file in less in a terminal window

Here's the content of the file without the wrap-around:

        # /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point> <type> <options> <dump> <pass>
# / was on /dev/sda1 during installation
UUID=4a143d08-8695-475b-8243-b13b56050fc2 / ext4 errors=remount-ro 0 1
/swapfile none swap sw 0 0

There are only two entries, and one of them is a swap file, which we can ignore. The other is being mounted at the root of the filesystem ( / ) and was on device /dev/sda1 at the time of installation. That's the first partition on the first hard drive, and it happens to contain an ext4 file system.

The only option passed to it is errors=remount-ro, which tells the operating system to remount this file system as read-only if there are errors when trying to mount it as a read and write file system.

So, there's no mention of how the access timestamp will be handled. Let's dig deeper and check out what /proc/mounts can tell us. We'll pipe the output from /proc/mounts through grep. Our search string will be "sda", the hard drive identifier.

We type the following:

cat /proc/mounts | grep "sda"

cat /proc/mounts | grep "sda" in a terminal window

Now we see the following options:

  • rw: The file system will be mounted as a read and write file system.
  • relatime: The file system will use the "relative atime" scheme to update the access timestamps.

Where did that come from? Well, the relatime scheme is used in the following situations:

  • When the defaults /etc/fstab option is used.
  • When the relatime /etc/fstab option is used.
  • When no access timestamp options are used in /etc/fstab, and you're using Linux kernel 2.6.30 or newer.

Our /etc/fstab entry for the ext4 file system didn't specify any access timestamp update options, so Linux made the sensible choice and used relatime.

Timestamps Are Important

Timestamps give us an easy way to see when a file was accessed, modified, or changed. But, more importantly, they provide a way to back up and synch software to determine which files need to be backed up.

The ability to manipulate timestamps will prove useful whenever you need to forcibly convince a program to include or ignore a file, or set of files.

Linux Commands

Files

tar · pv · cat · tac · chmod · grep · diff · sed · ar · man · pushd · popd · fsck · testdisk · seq · fd · pandoc · cd · $PATH · awk · join · jq · fold · uniq · journalctl · tail · stat · ls · fstab · echo · less · chgrp · chown · rev · look · strings · type · rename · zip · unzip · mount · umount · install · fdisk · mkfs · rm · rmdir · rsync · df · gpg · vi · nano · mkdir · du · ln · patch · convert · rclone · shred · srm · scp · gzip · chattr · cut · find · umask · wc · tr

Processes

alias · screen · top · nice · renice · progress · strace · systemd · tmux · chsh · history · at · batch · free · which · dmesg · chfn · usermod · ps · chroot · xargs · tty · pinky · lsof · vmstat · timeout · wall · yes · kill · sleep · sudo · su · time · groupadd · usermod · groups · lshw · shutdown · reboot · halt · poweroff · passwd · lscpu · crontab · date · bg · fg · pidof · nohup · pmap

Networking

netstat · ping · traceroute · ip · ss · whois · fail2ban · bmon · dig · finger · nmap · ftp · curl · wget · who · whoami · w · iptables · ssh-keygen · ufw · arping · firewalld

RELATED: Best Linux Laptops for Developers and Enthusiasts