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:
Linux 2.6.18-406.el5 x86_64 if it matters.
You can use something like:
/bin/date +%Y%m%d%H%M%S -d "$(/usr/bin/stat -c %x find.txt)"
With GNU tools:
find file -prune -printf '%TY%Tm%Td%TH%TM%TS\n'
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
find to do the same)).
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
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
The file modification time, could be formatted with date:
$ date -d @"$(stat -c %Y file1)" +'%Y%m%d%H%M%S'
%X for last access time and
%Z for last change.
However, the maximum resolution of
%Z is seconds.
For nanoseconds resolution use the
$ 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
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
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-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.
 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