<html>
  <head>
    <meta content="text/html; charset=windows-1252"
      http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <p>Hi Brad,</p>
    <p>I've done up a pure bash (other than smartctl and sudo) version
      of this with a few extra features.</p>
    <p>You can download it from
      <a class="moz-txt-link-freetext" href="http://www.sbts.com.au/files/drive-age.sh">http://www.sbts.com.au/files/drive-age.sh</a></p>
    <p>But here it is in text form</p>
    <p>There are a few long lines that will probably wrap in you mail
      software so either download it or fix those before running<br>
      Also, in the HELP() function the <------> are tabs. please
      replace before execution<br>
      <br>
      There are various things that could be shrunk into either less
      lines, or less verbose code.<br>
      eg: the declare's at the top of the script could be a single
      declare with multiple Variable Names;<br>
      Also there are uses of  "if then" statements that could be reduced
      to && etc.<br>
      I've left it as is to hopefully make it easier for you to follow<br>
    </p>
    <p>#!/bin/bash<br>
      <br>
      Init() {<br>
          local Idx=0;<br>
          declare -g -a Device;<br>
          declare -g -a Model;<br>
          declare -g -a Serial;<br>
          declare -g -a Hours;<br>
          declare -g -a Temperature;<br>
          declare -g -a TemperatureUnit;<br>
      <br>
          declare -g SMARTCTL='/usr/sbin/smartctl'<br>
          declare -g SUDO<br>
          [[ ! -u $SMARTCTL ]] && { # "no setUID so try using
      sudo"<br>
              read -rst5 SUDO < <( which sudo )<br>
              [[ -x "$SUDO" ]] && $SUDO -v -p 'Please enter your
      [sudo] password so we can run "smartctl -x": '<br>
              read -rst5 SMARTCTL < <( $SUDO which smartctl )<br>
              [[ ! -x $SMARTCTL ]] && { echo "We don't seem to
      be able to run 'smartctl' ($SMARTCTL)"; exit 9; }<br>
          }<br>
      }<br>
      <br>
      Scan() {<br>
          echo -n 'Scanning drives '<br>
          for Dev in /dev/sd? ; do<br>
              local Id='' Name='' Flags='' Value='' Worst='' Thresh=''
      Fail='' Raw='' J='';<br>
              Device[$Idx]="$Dev"<br>
              echo -n "."<br>
              while read -rst10 Id Name Flags Value Worst Thresh Fail
      Raw J; do<br>
                  [[ "$Id" == 'Device' ]] && [[ "$Name" ==
      'Model:' ]]  && {<br>
                      Model[$Idx]="${Flags} ${Value} ${Worst} ${Thresh}
      ${Fail} ${Raw} ${J}";<br>
                      continue;<br>
                  }<br>
                  [[ "$Id" == 'Serial' ]] && [[ "$Name" ==
      'Number:' ]] && {<br>
                      Serial[$Idx]="${Flags} ${Value} ${Worst} ${Thresh}
      ${Fail} ${Raw} ${J}";<br>
                      continue;<br>
                  }<br>
                  [[ "$Name" == 'Power_On_Hours' ]] && {<br>
                      Hours[$Idx]="$Raw";<br>
                      continue;<br>
                  }<br>
                  [[ "$Id" == 'Lifetime' ]] && \<br>
                      [[ "$Name" == 'Min/Max' ]] && \<br>
                          [[ "$Flags" == 'Temperature:' ]] && {<br>
                              Temperature[$Idx]="$Value";<br>
                              TemperatureUnit[$Idx]="$Worst";<br>
                              continue;<br>
                          }<br>
              done < <( $SUDO $SMARTCTL -x $Dev)<br>
              (( Idx++ ));<br>
          done<br>
          eval declare -g -a Index=( {0..$(( ${#Device[@]} -1 ))} ); #
      this just sets a default index order<br>
          echo " : Done"<br>
      }<br>
      <br>
      DisplayLines() { # $1 is format, remaining args are values<br>
          local fmt="$1"; shift<br>
          local I=0 maxI=${#Device[@]} J=0;<br>
          while (( I<maxI )); do<br>
              J=${Index[$I]}<br>
              local Hrs=${Hours[$J]}<br>
              local Y=0 D=0 H=0<br>
              (( Y = Hrs/(365*24) ))<br>
              (( H = Hrs % (365*24) ))<br>
              (( D = H/24 ))<br>
              (( H = H%24 ))<br>
              printf "$fmt" "${Device[$J]}" "${Model[$J]}" $Y $D $H
      "${Temperature[$J]}" "${TemperatureUnit[$J]}"<br>
              (( I++ ))<br>
          done<br>
      }<br>
      <br>
      Display(){<br>
          DisplayLines "%-8s - %-30s - %2u Years %3u Days %2u Hours -
      Temperature (min/max) %s %s\n"<br>
      }<br>
      <br>
      Display_Table(){<br>
          local
      L='--------------------------------------------------------------'<br>
          local I=${#Device[@]};<br>
          printf "  %-8.8s   %-36.36s
      ,-%5.5s---%4.4s---%5.5s-,-%11.11s-,\n" '' '' "$L" "$L" "$L" "$L"<br>
          printf ",-%-8.8s-,-%-36.36s-| %5s   %4s   %5s | %11.11s |\n"
      "$L" "$L" '' 'Age' '' ' (min/max) '<br>
          printf "| %-8s | %-36s | %5s | %4s | %5s | %11.11s |\n"
      'Device' 'Model' 'Years' 'Days' 'Hours' 'Temperature'<br>
          printf
      "|-%-8.8s-|-%-36.36s-|-%5.5s-|-%4.4s-|-%5.5s-|-%11.11s-|\n" "$L"
      "$L" "$L" "$L" "$L" "$L"<br>
          DisplayLines "| %-8s | %-36.36s | %5u | %4u | %5u | %9s %1.1s
      |\n"<br>
          printf
      "'-%-8.8s-'-%-36.36s-'-%5.5s-'-%4.4s-'-%5.5s-'-%11.11s-'\n" "$L"
      "$L" "$L" "$L" "$L" "$L"<br>
      }<br>
      <br>
      Build_Index_Sorted() { # $1 = Reverse Sort Order [true|false]<br>
          [[ ${1:-up} == up ]] && Reverse=false;<br>
          [[ ${1:-up} == down ]] && Reverse=true;<br>
          local maxI=${#Index[@]}; #(( maxI -- )) # adjust for zero
      offset<br>
          unset Index; declare -g -a Index;<br>
          local I=0;<br>
          while (( I<maxI )); do<br>
              local J=0 current=0<br>
              while [[ "z${Index[@]}z" =~ "${current}" ]]; do ((
      current++ )); done # find first Item not in Index<br>
              while (( J<maxI )); do<br>
                  [[ "z"${Index[@]}"z" =~ "${J}" ]] && { (( J++
      )); continue; }<br>
                  if $Reverse; then<br>
                      ! (( ${Hours[$J]} <= ${Hours[$current]} ))
      && (( current =  J ));<br>
                  else<br>
                      (( ${Hours[$J]} <= ${Hours[$current]} ))
      && (( current =  J ));<br>
                  fi<br>
                  (( J++ ))<br>
              done<br>
              Index[$I]=$current;<br>
              (( I++ ))<br>
          done<br>
      }<br>
      <br>
      HELP() { # NOTE the <------> is a tab. please replace before
      execution<br>
          cat <<-EOF<br>
      <------>usage: ${0##*/} [-n | -t]<br>
      <------>    -L|l : Line based output<br>
      <------>    -T|t : Table based output<br>
      <------>    -s   : Sort Youngest to Oldest<br>
      <------>    -S   : Sort Oldest to Youngest<br>
      <------>EOF<br>
      }<br>
      <br>
      Main() {<br>
          Init<br>
          Scan<br>
          [[ "$@" =~ -[s] ]] && Build_Index_Sorted up<br>
          [[ "$@" =~ -[S] ]] && Build_Index_Sorted down<br>
          [[ "$@" =~ -[tT] ]] && { Display_Table; return; }<br>
          [[ "$@" =~ -[lL] ]] && { Display; return; }<br>
          HELP<br>
      }</p>
    <p>Main "$@"<br>
      <br>
    </p>
    <br>
    <div class="moz-cite-prefix">On 08/05/17 08:40, Brad Campbell wrote:<br>
    </div>
    <blockquote
      cite="mid:595b9979-2ca0-cd11-daa3-27219f31603b@fnarfbargle.com"
      type="cite">#!/bin/bash
      <br>
      declare -a ARR
      <br>
      CNT=0
      <br>
      echo -n Scanning drives.
      <br>
      for i in /dev/sd? ; do
      <br>
          echo -n "."
      <br>
          SMART=$(smartctl -x $i)
      <br>
          hrs=$(echo "$SMART" | grep Power_On_Hours | awk '{print $8}' |
      egrep -v '[[:alpha:]]')
      <br>
          [ -z "$hrs" ] && hrs=$(echo "$SMART" | grep 'Power-on
      Hours' | awk '{print $4}')
      <br>
          [ -z "$hrs" ] && hrs=$(echo "$SMART" | egrep '^# 1' |
      cut -c 60- | awk '{print $1}')
      <br>
          model="$(echo "$SMART" | grep 'Device Model:' | cut -f2 -d':'
      | xargs)"
      <br>
          if [ -n "$hrs" ]  ; then
      <br>
              ARR[$CNT]="$hrs $i $model"
      <br>
              CNT=$((CNT+1))
      <br>
          fi;
      <br>
      done
      <br>
      echo Done scanning
      <br>
      IFS=$'\n' sorted=($(sort -n <<<"${ARR[*]}"))
      <br>
      for i in ${sorted[*]} ; do
      <br>
          hrs=`awk '{print $1}' <<< $i`
      <br>
          dev=`awk '{print $2}' <<< $i`
      <br>
          model=`cut -f3- -d" " <<< $i`
      <br>
          Y=$((hrs/(365*24)))
      <br>
          hrs=$((hrs%(365*24)))
      <br>
          D=$((hrs/24))
      <br>
          hrs=$((hrs%24))
      <br>
          echo $dev" - "$model" - "$Y years $D days $hrs hours
      <br>
      done
      <br>
    </blockquote>
    <br>
    <div class="moz-signature">-- <br>
      <style>
    div.sig {
      border: 1px solid black;
      height: auto;
      float: left;
      padding: 1em;
    }
    span.left { 
        width: 4em;
        float: left;
    }
    span.pulseit { 
      -webkit-animation: mymove 1s infinite; /* Chrome, Safari, Opera */
      animation: pulse 2s infinite;
    }
        @keyframes pulse { 50% {font-size: 0.9em;} }
  </style>
      Regards<br>
      David Godfrey<br>
      <br>
      <div class="sig">
        <br>
        <span class="left"> mb:<br>
          <span class="pulseit">chat:</span> </span> <span
          style="float: right;"> 0437 286 200<br>
          with <em>dcg_mx</em> at <a
            href="http://matrix.to/#/#sbts:matrix.org">#sbts:matrix.org</a>
          <p style="font-size:smaller;">Chat is via matrix.org.<br>
            There are clients available for All Operating Systems and
            Hardware devices.<br>
            Including Linux, Android, Windows, Mac, iOS<br>
            I'd recommend the multiplatform RIOT client as the best
            starting point.<br>
            with RIOT web the easiest on any PC </p>
        </span>
      </div>
    </div>
  </body>
</html>