I want to get the modification time of a file in a specific format.
How can I do that ?
I know about
stat -c %x find.txt
but I need this format:
yyyymmddhh24miss
I'm using ksh
on Linux 2.6.18-406.el5 x86_64
if it matters.
I want to get the modification time of a file in a specific format.
How can I do that ?
I know about
stat -c %x find.txt
but I need this format:
yyyymmddhh24miss
I'm using ksh
on Linux 2.6.18-406.el5 x86_64
if it matters.
With GNU tools:
find file -prune -printf '%TY%Tm%Td%TH%TM%TS\n'
Or
date -r file +%Y%m%d%H%M%S.%N
(though beware that for symlinks, that displays the modification time of the target of the symlink, not the symlink itself (which may be just as well as who cares about the mtime of a symlink, see -L
with find
to do the same)).
If your ksh
is ksh93
and it has been built with the date
builtin enabled:
command /opt/ast/bin/date -m -f %Y%m%d%H%M%S.%N file
(command /opt/ast/bin/date
invokes the date
builtin bound to /opt/ast/bin/date
, if you add /opt/ast/bin
at the front of $PATH
, those builtins will be invoked automatically when you call them by name).
If you don't care for the fractional part, remove the .%N
or for find
, replace %TS
with %.2TS
.
Note that the time will be given in the current timezone. As this date format doesn't include the UTC offset, it can be ambiguous. For instance in my mainland British timezone:
$ date -r file1
Sun 30 Oct 01:00:00 BST 2016
$ date -r file2
Sun 30 Oct 01:00:00 GMT 2016
Those two files have a modification time that are 3600 seconds apart, one before, one after the change to winter time but still at the same wall clock time (as that clock has been moved back one hour in the interval).
$ find file? -prune -printf '%TY%Tm%Td%TH%TM%TS\n'
20161030010000.0000000000
20161030010000.0000000000
To have unambiguous times, you can include the UTC offset:
$ find file? -prune -printf '%TY%Tm%Td%TH%TM%TS%Tz\n'
20161030010000.0000000000+0100
20161030010000.0000000000+0000
Or give the time in UTC:
$ TZ=UTC0 find file? -prune -printf '%TY%Tm%Td%TH%TM%TS\n'
20161030000000.0000000000
20161030010000.0000000000
file
is a directory, -prune
has no effect.
zsh/zstat
solution for completeness...
Nov 4, 2018 at 21:06
You can use something like:
/bin/date +%Y%m%d%H%M%S -d "$(/usr/bin/stat -c %x find.txt)"
The file modification time, could be formatted with date:
$ date -d @"$(stat -c %Y file1)" +'%Y%m%d%H%M%S'
Use %X
for last access time and %Z
for last change.
However, the maximum resolution of %X
, %Y
and %Z
is seconds.
For nanoseconds resolution use the %x
, %y
and %z
options:
$ date -d "$(stat -c %y file1)" +'%Y%m%d%H%M%S.%N'
20151101020000.012345678
As we are using date already, we can simplify by using date's -r
option, or we can use find's formatted output:
$ date -r file1 +'%Y%m%d%H%M%S%z'
20151101010000-0500
$ find file1 -printf '%TY%Tm%Td%TH%TM%2.2TS%Tz\n'
20151101010000-0500
The resolution of the above commands is seconds. If nanoseconds are needed:
$ date -r file1 +'%Y%m%d%H%M%S.%N%z'
20151101010000.012345678-0500
$ find file1 -printf '%TY%Tm%Td%TH%TM%TS%Tz\n'
20151101010000.0123456780-0500
Those two commands give modification time
In date there is no way to get access or status time with the -r
option.
In find: Change %T to %A for access time and to %C for status change time
Please note that all the above commands are affected by the time zone used:
$ date -r file1 +'%Y%m%d%H%M%S.%N%z'
20151101010000.012345678
$ TZ=GMT0 date -r file1 +'%Y%m%d%H%M%S.%N%z'
20151101060000.012345678
Note the Hour change from 01
to 06
. That happens because the computer used had a time zone set for America/New_York
. When the time is calculated at the GMT0
offset (aka GMT
or GMT+0
or GMT-0
) its value increase in 5 hours.
Also, the use of local time values (if incomplete) may present equal values when they are actually different:
$ date -r file1 +'%Y%m%d%H%M%S.%N'; date -r file2 +'%Y%m%d%H%M%S.%N'
20151101010000.012345678
20151101010000.012345678
That's why the tailing %z
is needed for local times:
$ date -r file1 +'%Y%m%d%H%M%S.%N%z'; date -r file2 +'%Y%m%d%H%M%S.%N%z'
20151101010000.012345678-0500
20151101010000.012345678-0400
That makes the values different. But this kind of format makes sorting by time difficult. That is why the best solution is to use GMT
times because the time offset (%z
) is always 0
and can be omitted:
$ ( TZ=GMT0; date -r file1 +'%Y%m%d%H%M%S.%N'; date -r file2 +'%Y%m%d%H%M%S.%N')
20151101060000.012345678
20151101050000.012345678
And sorting is possible.
[1] Values used to touch files used.
touch -m -d '20151101 01:00:00.012345678-05' file1
touch -a -d '20151101 01:00:00.987654321-05' file1
touch -m -d '20151101 01:00:00.012345678-04' file2
touch -a -d '20151101 01:00:00.987654321-04' file2