Search code examples
bashdatetimestamplsiso

bash script to generate iso-time from output of older BSD-`ls`


I would like to generate an iso-style time info (YYYY-MM-DDTmm:hh:ss) on a bsd-ish system with an older ls command (man states it's a BSD-ls) and no --time-style option. The best I get is

$ ls -lT log.out
-rw-r--r--  1 admin4  staff  49152 Jul 17 09:38:38 2018 log.out

Is there a simple way to transform this time information within a bash-script into iso-style?

$ timestamp="$(ls -lT log.out | iso-timestamp-gen)"

Your help will be highly appreciated


Solution

  • To solve our problem

    timestamp="$(ls -lT log.out | iso-timestamp-gen)"
    

    @Hamidreza pointed us into the direktion of the date command: One of our engineers came up with this slender inline solution:

    timestamp=$(date -j -f '%b %e %T %Y' \
        "$(ls -lT $f | awk '{ print $6, $7, $8, $9 }')" \
        +'%F_%T')
    

    where the variable f contains the name of the file to be considered. In line 2 awk extracts the date-part (fields 6 upto 9) from the output of ls -lT.

    Together with this "DateToConvert" date is fed a matching input format "%b %e %T %Y" and the requested output format "%F_%T". We looked up the conversion specifications in strftime(3).

    Up to now neither of us was aware that you could use date not only for reading and setting the system clock but also for converting dates from one format to another format:

    date -j -f "${InputFormat}" "${DateToConvert}" +"${OutputFormat}"
    

    With some embarassment we confessed this to each other and decided to make good use of the new insight. A couple of hours later we added the following new helper to our toolbox. It extracts the date from the output of ls -lT and converts it to other formats. So far we included only the iso-format and a format which is handy when using the touch(1) command. This list may be expanded in the future.

    #!/bin/bash
    #
    # conv-date-of-llT.sh
    #   convert date output of ls -lT ($OSTYPE == darwin14)
    #       - to iso-format YYYY-MM-DD_hh:mm:ss or
    #       - to "touch" format: [[CC]YY]MMDDhhmm[.SS]
    #
    # hppo, 2018-07-20
    
    # strip $0 of path and ext
    Arg0="${0##*/}"     # peel off path
    Arg0="${Arg0%%.*}"  # peel off ext
    
    USAGE="${Arg0} [ -iso | -touch ]"
    
    # select output format
    case "fmt$1" in
        fmt|fmt-iso|fmtiso)     # YYYY-MM-DD_hh:mm:ss
            OutputFormat="%F_%T" ;;
        fmt-touch|fmttouch)     # YYYYMMDDhhmm
            OutputFormat="%Y%m%d%H%M" ;;
        *)
            1>&2 echo -e "${Arg0}: no such output format '$1'\nUsage: ${USAGE}"; exit 1 ;;
    esac
    
    # input: output of "ls -lT file" on darwin-14
    #       -rwxr-xr-x  1 admin4  staff  387 Jul 17 01:38:24 2018 file
    #       1       2 3   4  5   6   7  8        9    10
    #
    # Field 6 - 9: month(%b) day(%e) time(%T) year(%Y), cf strftime(3)
    InputFormat="%b %e %T %Y"
    
    # assume stdin is fed by output of ls -lT
    DateToConvert="$(awk '{ print $6, $7, $8, $9 }')"
    
    date -j -f "${InputFormat}" "${DateToConvert}" +"${OutputFormat}"