3

I am trying to obtain the full date (created or modified) of a particular file for passing to another program. I have tried variations of options with the ls command but none provide a full date for files less than 6 months old and I have limit usage of the options. When I try certain options I have seen trying to research this I get the following message:

usage: ls [-1ACFHLNRabcdefgilmnopqrstuxEUX] [File...]

None of which seems to provide what I needs as far as I can tell so I tried to use the stat command but it is not available to me.

I am using the Korn shell on AIX 5.3 which has limited commands available, can anyone suggest another way that I might be able to obtain a file's created or modified date as a full date (either dd/mm/yyyy or yyyy/mm/dd).

  • @StéphaneChazelas My apologies for not knowing that. It is my first time using Unix and I only know that I use PuTTY to log in and the shell is korn. How would I find out what the OS is? – Matt_Roberts Jan 15 '16 at 13:57
  • uame -rs returned AIX 3 – Matt_Roberts Jan 15 '16 at 14:13
  • For older files, it should still give you the full date (year, month and day), just not the time. It's for newer files that it wouldn't give you the year. – Stéphane Chazelas Jan 15 '16 at 14:25
  • 1
    AIX 3? AIX 3.2 1992 / AIX 3.1, February 1990 / AIX 3.0 1989 - that's going some!

    Can you try oslevel just in case that uname doesn't give what you might expect?

    – EightBitTony Jan 15 '16 at 14:46
  • 2
    @EightBitTony oslevel returns 5.3.0.0 – Matt_Roberts Jan 15 '16 at 15:08
  • So, AIX 5.3 - much less worrying, doesn't affect your answer, but does calm my nerves a bit (5.3 is long out of support obviously, but not as bad as AIX 3 would have been!). For reference, oslevel is the approved method of getting the version of out AIX. man oslevel for all the flags. – EightBitTony Jan 15 '16 at 15:10
  • @EightBitTony unfortunately man also does not work on the version I have access to :( – Matt_Roberts Jan 15 '16 at 15:39

3 Answers3

12

With ls, though you may not always be able to get the time, you should be able to derive the date (year, month and day of the month).

In the C locale, the date output in ls -l should either be Mmm dd HH:MM for recent files (and you should be able to derive the year (either this year or the previous one) or Mmm dd YYYY for older files or files with a modification time in the future. So you should always be able to get the date (YYYY-mm-dd) out of that:

eval "$(date +'year=%Y month=%m')"
LC_ALL=C ls -dln file | awk -v y="$year" -v m="$month" '{
  month = index("--JanFebMarAprMayJunJulAugSepOctNovDec", $6) / 3
  day = $7
  if ($8 ~ /:/)
    year = y - (month > m)
  else
    year = $8
  printf "%04d-%02d-%02d\n", year, month, day
  exit}'

Now, if you want the full modification time with maximum precision, I'm afraid there is no standard command for that.

You'll find some ls implementations that have options for that (ls --full-time with GNU ls or -D <format> with FreeBSD ls for instance)

There exist a number of different and incompatible implementations of a stat command (IRIX, zsh builtin, GNU, BSD) that can give you that.

Or you could use the -printf predicate of GNU find. Or the -r option of GNU date.

Not all implementations will give you sub-second granularity. And beware of time zones and DST as depending on the format you choose and the timezone you're in, a given output may be ambiguous and refer to more than one possible date.

For symlinks, you may also want to ask yourself whether it's the modification time of the link or its target you're after. Some of the options mentioned here will do one or the other by default and some of them can be told to do one or the other on demand.

  • zsh stat: stat -F '%Y-%m-%d %T.%N %z' +mtime file
    1992-05-13 14:57:00.123368710 +0100
  • GNU stat: stat -c %y file
    1992-05-13 14:57:00.123368710 +0100
  • BSD stat: stat -t '%F %T %z' -f %Sm file
    1992-05-13 14:57:00 +0100
  • IRIX stat: stat -m file
  • GNU find: find file -prune -printf '%TF %TT %Tz\n'
    1992-05-13 14:57:00.1233687100 +0100
  • GNU date: date -r file '+%F %T.%N %z'
    1992-05-13 14:57:00.123368710 +0100
  • FreeBSD ls: ls -D '[%F %T %z]' -l file
    -r-xr-xr-x 2 bin bin 372298 [1992-05-13 14:57:00 +0100] file
  • GNU ls: ls --full-time -l file
    -r-xr-xr-x 2 bin bin 372298 1992-05-13 14:57:00.123368710 +0100 file
  • ast-open ls: ls -Z '%(mtime:time=%F %T.%N %z)s'
    1992-05-13 14:57:00.123368710 +0100

AIX, which your ls synopsis suggests you may be using has an istat command (AIX 5.3 man page) that displays dates in full (without sub-second granularity, and ambiguous unless you force TZ to UTC0), though not that easy to parse:

$ LC_ALL=C TZ=UTC0 istat file
Inode 10360 on device 10/6    File
Protection: r-xr-xr-x
Owner: 2(bin)     Group: 2(bin)
Link count: 2     Length 372298 bytes

Last updated: Wed May 13 14:08:13 1992 Last modified: Wed May 13 13:57:00 1992 Last accessed: Sun Jan 31 15:49:23 1993

Also note that for symlinks, you'll get the date of the target of the symlink, not the symlink itself.

If you don't have access to any of those, your best bet for portability may be perl:

$ perl -MPOSIX -le 'print strftime("%Y-%m-%d %T %z", localtime((lstat(shift))[9]))' file
1992-05-13 14:57:00 +0100

Note that few systems have a creation time for files (sometimes called birth time), and there's no standard API, let alone command to query it, so the situation is even worse than for the modification time.

1

If you have GNU ls:

ls --time-style=long-iso -l

or

ls --time-style=+FMT -l

where FMT follows date command format. In your case:

ls --time-style=+%Y/%m/%d -l
JJoao
  • 12,170
  • 1
  • 23
  • 45
  • Hi JJoao, sadly this does not work as the only options I am able to use are those shown in my question. I get the following when I try your method: pgms>ls --time-style=+%Y/%m/%d -l ls: illegal option -- - ls: illegal option -- - ls: illegal option -- y ls: illegal option -- = ls: illegal option -- + ls: illegal option -- % ls: illegal option -- Y ls: illegal option -- / ls: illegal option -- % ls: illegal option -- / ls: illegal option -- % usage: ls [-1ACFHLNRabcdefgilmnopqrstuxEUX] [File...] – Matt_Roberts Jan 15 '16 at 13:39
1

Here is a POSIX function to do that:

mtime() {
   touch -r "$1" /etc/fstab
   diff -u /etc/fstab /dev/null | head -n 1 | cut -f 2
}

Result:

$ mtime ~/.profile
2019-07-01 06:25:34.000000000 -0500

http://cup.github.io/autumn/util/path/file-mtime