5

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.

2
  • unix and /bin/ksh
    – ANOUK_prog
    May 27, 2016 at 12:53
  • Linux 2.6.18-406.el5 x86_64 and /bin/ksh
    – ANOUK_prog
    May 27, 2016 at 12:55

3 Answers 3

5

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
3
  • Unless file is a directory, -prune has no effect.
    – user79743
    May 29, 2016 at 22:28
  • 1
    Yes, which is why it's safe to use on any kind of file, and you want to use it in case the file might be of type directory. Nov 4, 2018 at 21:01
  • You could as well include a zsh/zstat solution for completeness... Nov 4, 2018 at 21:06
3

You can use something like:

/bin/date +%Y%m%d%H%M%S -d "$(/usr/bin/stat -c %x find.txt)"
1

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


About Time Zone

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

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .