Is it possible to change the file modification time without changing the file acess time?
Modification and Access time of a file
filestimestamps
Related Solutions
There are 3 kind of "timestamps":
- Access - the last time the file was read
- Modify - the last time the file was modified (content has been modified)
- Change - the last time meta data of the file was changed (e.g. permissions)
To display this information, you can use stat
which is part of the coreutils.
stat
will show you also some more information like the device, inodes, links, etc.
Remember that this sort of information depends highly on the filesystem and mount options. For example if you mount a partition with the noatime
option, no access information will be written.
A utility to change the timestamps would be touch
.
There are some arguments to decide which timestamp to change (e.g. -a for access time, -m for modification time) and to influence the parsing of a new given timestamp.
See man touch
for more details.
touch
can become handy in combination with cp -u
("copy only when the SOURCE file is newer than the destination file or when the destination file is missing") or for the creation of empty marker files.
In testing on this linux system. The usual way to test file times is the shell:
[ file1 -nt file2 ] && echo "yes"
Seems to work with seconds. This, which will touch the files with a time difference less than a second, doesn't detect that difference:
$ touch file2; sleep 0.1; touch file1; [ file1 -nt file2 ] && echo "yes"
To confirm the issue (time after the dot is nanoseconds):
$ ls --time-style=full-iso -l file?
-rw-r--r-- 1 user user 0 2017-06-23 01:37:01.707387495 -0400 file1
-rw-r--r-- 1 user user 0 2017-06-23 01:37:01.599392538 -0400 file2
The file1
is (a bit) newer than file2
.
The problem now will be to correctly process the time value.
One solution is to use a formatted output of ls:
$ ls --time-style=+%s.%N -l file?
-rw-r--r-- 1 user user 0 1498196221.707387495 file1
-rw-r--r-- 1 user user 0 1498196221.599392538 file2
Extracting the time to two variables (without the dot):
$ file1time=$(ls --time-style=+%s%N -l file1 | awk "{print(\$6)}")
$ file2time=$(ls --time-style=+%s%N -l file2 | awk "{print(\$6)}")
And compare the times (times with nanoseconds just barely fit in a 64 bit value. If your system does not use 64 bit, this comparison will fail):
$ [ $file1time -gt $file2time ] && echo "yes"
yes
That shows that file1
is newer than file2
If ls
fails to have the format needed, then you may try stat.
$ stat file1
File: file1
Size: 0 Blocks: 0 IO Block: 4096 regular file
Device: 805h/2053d Inode: 9180838 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1000/ user) Gid: ( 1000/ user)
Access: 2017-06-23 01:37:01.707387495 -0400
Modify: 2017-06-23 01:37:01.707387495 -0400
Change: 2017-06-23 01:37:01.707387495 -0400
Birth: -
If the output shows nanoseconds, the we will need date to parse (and format) the time.
$ stat --printf='%y\n' file1
2017-06-23 01:37:01.707387495 -0400
$ date +'%s%N' -d "$(stat --printf='%y\n' file1)"
1498196221707387495
The rest is the same, assign the results of file1 and file2 to two variables and numerically compare them.
Best Answer
The
utime
/utimes
syscall lets you set the access and modification time arbitrarily. So you canstat
the file, then useutime
to change only one of them. From the man page: