2

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
11

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 -dn 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.

  • Hi Stéphane, the only thing that worked was your suggestion of perl. Thank you! – Matt_Roberts Jan 15 '16 at 13:46
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
  • 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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.