Datumsarithmetik in Unix-Shell-Skripten

  • Ich muss Datumsberechnungen in Unix-Shell-Skripts ausführen, die ich zur Steuerung der Ausführung von Programmen von Drittanbietern verwende.

    Ich verwende eine Funktion zum Erhöhen eines Tages und eine weitere zum Verringern:

     IncrementaDia(){
    echo $1 | awk '
    BEGIN {
            diasDelMes[1] = 31
            diasDelMes[2] = 28
            diasDelMes[3] = 31
            diasDelMes[4] = 30
            diasDelMes[5] = 31
            diasDelMes[6] = 30
            diasDelMes[7] = 31
            diasDelMes[8] = 31
            diasDelMes[9] = 30
            diasDelMes[10] = 31
            diasDelMes[11] = 30
            diasDelMes[12] = 31
    }
    {
            anio=substr($1,1,4)
            mes=substr($1,5,2)
            dia=substr($1,7,2)
    
            if((anio % 4 == 0 && anio % 100 != 0) || anio % 400 == 0)
            {
                    diasDelMes[2] = 29;
            }
    
            if( dia == diasDelMes[int(mes)] ) {
                    if( int(mes) == 12 ) {
                            anio = anio + 1
                            mes = 1
                            dia = 1
                    } else {
                            mes = mes + 1
                            dia = 1
                    }
            } else {
                    dia = dia + 1
            }
    }
    END {
            printf("%04d%02d%02d", anio, mes, dia)
    }
    '
    }
    
    if [ $# -eq 1 ]; then
            tomorrow=$1
    else
            today=$(date +"%Y%m%d")
            tomorrow=$(IncrementaDia $hoy)
    fi
     

    aber jetzt muss ich komplexere arithmetik machen.

    Was ist der beste und kompatibelere Weg, dies zu tun?

    09 August 2008
    ggasp
14 answers
  • Angenommen, Sie haben GNU-Datum wie folgt:

     date --date='1 days ago' '+%a'
     

    Und ähnliche Sätze .

    12 February 2015
    GillesBetty
  • Hier finden Sie eine einfache Möglichkeit, Datumsberechnungen in Shell-Skripten durchzuführen.

     meetingDate='12/31/2011' # MM/DD/YYYY Format
    reminderDate=`date --date=$meetingDate'-1 day' +'%m/%d/%Y'`
    echo $reminderDate
     

    Nachfolgend sind folgende Angaben aufgeführt Weitere Variationen der Datumsberechnung, die mit dem Dienstprogramm date erreicht werden können. http://www.cyberciti.biz/tips/linux-unix-get-yesterdays-tomorrows-date.html http://www.cyberciti.biz/faq/linux-unix-formatting-dates-for-display/

    Das hat bei RHEL funktioniert.

    31 May 2012
    Erick Robertson
  • Ich habe ein Bash-Skript zum Konvertieren von in Englisch ausgedrückten Datumsangaben in herkömmliche MM / TT / JJJJ-Datums geschrieben. Es heißt ComputeDate .

    Hier einige Beispiele für seine Verwendung. Der Kürze halber habe ich die Ausgabe jedes Aufrufs in der gleichen Zeile wie der Aufruf platziert, getrennt durch einen Doppelpunkt (:). Die nachstehenden Anführungszeichen sind nicht erforderlich, wenn ComputeDate ausgeführt wird:

     $ ComputeDate 'yesterday': 03/19/2010
    $ ComputeDate 'yes': 03/19/2010
    $ ComputeDate 'today': 03/20/2010
    $ ComputeDate 'tod': 03/20/2010
    $ ComputeDate 'now': 03/20/2010
    $ ComputeDate 'tomorrow': 03/21/2010
    $ ComputeDate 'tom': 03/21/2010
    $ ComputeDate '10/29/32': 10/29/2032
    $ ComputeDate 'October 29': 10/1/2029
    $ ComputeDate 'October 29, 2010': 10/29/2010
    $ ComputeDate 'this monday': 'this monday' has passed.  Did you mean 'next monday?'
    $ ComputeDate 'a week after today': 03/27/2010
    $ ComputeDate 'this satu': 03/20/2010
    $ ComputeDate 'next monday': 03/22/2010
    $ ComputeDate 'next thur': 03/25/2010
    $ ComputeDate 'mon in 2 weeks': 03/28/2010
    $ ComputeDate 'the last day of the month': 03/31/2010
    $ ComputeDate 'the last day of feb': 2/28/2010
    $ ComputeDate 'the last day of feb 2000': 2/29/2000
    $ ComputeDate '1 week from yesterday': 03/26/2010
    $ ComputeDate '1 week from today': 03/27/2010
    $ ComputeDate '1 week from tomorrow': 03/28/2010
    $ ComputeDate '2 weeks from yesterday': 4/2/2010
    $ ComputeDate '2 weeks from today': 4/3/2010
    $ ComputeDate '2 weeks from tomorrow': 4/4/2010
    $ ComputeDate '1 week after the last day of march': 4/7/2010
    $ ComputeDate '1 week after next Thursday': 4/1/2010
    $ ComputeDate '2 weeks after the last day of march': 4/14/2010
    $ ComputeDate '2 weeks after 1 day after the last day of march': 4/15/2010
    $ ComputeDate '1 day after the last day of march': 4/1/2010
    $ ComputeDate '1 day after 1 day after 1 day after 1 day after today': 03/24/2010
     

    Ich habe dieses Skript als Antwort auf dieses Problem hinzugefügt, weil es veranschaulicht, wie Datumsberechnungen über eine Reihe von Bash-Funktionen ausgeführt werden, und diese Funktionen können sich für andere als nützlich erweisen. Es behandelt Schaltjahre und Sprung Jahrhunderte richtig:

     #! /bin/bash
    #  ConvertDate -- convert a human-readable date to a MM/DD/YY date
    #
    #  Date ::= Month/Day/Year
    #        |  Month/Day
    #        |  DayOfWeek
    #        |  [this|next] DayOfWeek
    #        |  DayofWeek [of|in] [Number|next] weeks[s]
    #        |  Number [day|week][s] from Date
    #        |  the last day of the month
    #        |  the last day of Month
    #
    #  Month ::= January | February | March | April | May | ...  | December
    #  January  ::= jan | january | 1
    #  February  ::= feb | january | 2
    #  ...
    #  December ::=  dec | december | 12
    #  Day   ::= 1 | 2 | ... | 31
    #  DayOfWeek ::= today | Sunday | Monday | Tuesday | ...  | Saturday
    #  Sunday    ::= sun*
    #  ...
    #  Saturday  ::= sat*
    #
    #  Number ::= Day | a
    #
    #  Author: Larry Morell
    
    if [ $# = 0 ]; then
       printdirections $0
       exit
    fi
    
    
    
    # Request the value of a variable
    GetVar () {
       Var=$1
       echo -n "$Var= [${!Var}]: "
       local X
       read X
       if [ ! -z $X ]; then
          eval $Var="$X"
       fi
    }
    
    IsLeapYear () {
       local Year=$1
       if [ $[20$Year % 4]  -eq  0 ]; then
          echo yes
       else
          echo no
       fi
    }
    
    # AddToDate -- compute another date within the same year
    
    DayNames=(mon tue wed thu fri sat sun )  # To correspond with 'date' output
    
    Day2Int () {
       ErrorFlag=
       case $1 in
          -e )
             ErrorFlag=-e; shift
             ;;
       esac
       local dow=$1
       n=0
       while  [ $n -lt 7 -a $dow != "${DayNames[n]}" ]; do
          let n++
       done
       if [ -z "$ErrorFlag" -a $n -eq 7 ]; then
          echo Cannot convert $dow to a numeric day of wee
          exit
       fi
       echo $[n+1]
    
    }
    
    Months=(31 28 31 30 31 30 31 31 30 31 30 31)
    MonthNames=(jan feb mar apr may jun jul aug sep oct nov dec)
    # Returns the month (1-12) from a date, or a month name
    Month2Int () {
       ErrorFlag=
       case $1 in
          -e )
             ErrorFlag=-e; shift
             ;;
       esac
       M=$1
       Month=${M%%/*}  # Remove /...
       case $Month in
          [a-z]* )
             Month=${Month:0:3}
             M=0
             while [ $M -lt 12 -a ${MonthNames[M]} != $Month ]; do
                let M++
             done
             let M++
       esac
       if [  -z "$ErrorFlag" -a $M -gt 12 ]; then
          echo "'$Month' Is not a valid month."
          exit
       fi
       echo $M
    }
    
    # Retrieve month,day,year from a legal date
    GetMonth() {
       echo ${1%%/*}
    }
    
    GetDay() {
       echo $1 | col / 2
    }
    
    GetYear() {
       echo ${1##*/}
    }
    
    
    AddToDate() {
    
       local Date=$1
       local days=$2
       local Month=`GetMonth $Date`
       local Day=`echo $Date | col / 2`   # Day of Date
       local Year=`echo $Date | col / 3`  # Year of Date
       local LeapYear=`IsLeapYear $Year`
    
       if [ $LeapYear = "yes" ]; then
          let Months[1]++
       fi
       Day=$[Day+days]
       while [ $Day -gt ${Months[$Month-1]} ]; do
           Day=$[Day -  ${Months[$Month-1]}]
           let Month++
       done
       echo "$Month/$Day/$Year"
    }
    
    # Convert a date to normal form
    NormalizeDate () {
       Date=`echo "$*" | sed 'sX  *X/Xg'`
       local Day=`date +%d`
       local Month=`date +%m`
       local Year=`date +%Y`
       #echo Normalizing Date=$Date > /dev/tty
       case $Date in
          */*/* )
             Month=`echo $Date | col / 1 `
             Month=`Month2Int $Month`
             Day=`echo $Date | col / 2`
             Year=`echo $Date | col / 3`
             ;;
          */* )
             Month=`echo $Date | col / 1 `
             Month=`Month2Int $Month`
             Day=1
             Year=`echo $Date | col / 2 `
             ;;
          [a-z]* ) # Better be a month or day of week
             Exp=${Date:0:3}
             case $Exp in
                jan|feb|mar|apr|may|june|jul|aug|sep|oct|nov|dec )
                   Month=$Exp
                   Month=`Month2Int $Month`
                   Day=1
                   #Year stays the same
                   ;;
                mon|tue|wed|thu|fri|sat|sun )
                   # Compute the next such day
                   local DayOfWeek=`date +%u`
                   D=`Day2Int $Exp`
                   if [ $DayOfWeek -le $D ]; then
                      Date=`AddToDate $Month/$Day/$Year $[D-DayOfWeek]`
                   else
                      Date=`AddToDate $Month/$Day/$Year $[7+D-DayOfWeek]`
                   fi
    
                   # Reset Month/Day/Year
                   Month=`echo $Date | col / 1 `
                   Day=`echo $Date | col / 2`
                   Year=`echo $Date | col / 3`
                   ;;
                * ) echo "$Exp is not a valid month or day"
                    exit
                   ;;
                esac
             ;;
          * ) echo "$Date is not a valid date"
              exit
             ;;
       esac
       case $Day in
          [0-9]* );;  # Day must be numeric
          * ) echo "$Date is not a valid date"
              exit
             ;;
       esac
          [0-9][0-9][0-9][0-9] );;  # Year must be 4 digits
          [0-9][0-9] )
              Year=20$Year
          ;;
       esac
       Date=$Month/$Day/$Year
       echo $Date
    }
    # NormalizeDate jan
    # NormalizeDate january
    # NormalizeDate jan 2009
    # NormalizeDate jan 22 1983
    # NormalizeDate 1/22
    # NormalizeDate 1 22
    # NormalizeDate sat
    # NormalizeDate sun
    # NormalizeDate mon
    
    ComputeExtension () {
    
       local Date=$1; shift
       local Month=`GetMonth $Date`
       local Day=`echo $Date | col / 2`
       local Year=`echo $Date | col / 3`
       local ExtensionExp="$*"
       case $ExtensionExp in
          *w*d* )  # like 5 weeks 3 days or even 5w2d
                ExtensionExp=`echo $ExtensionExp | sed 's/[a-z]/ /g'`
                weeks=`echo $ExtensionExp | col  1`
                days=`echo $ExtensionExp | col 2`
                days=$[7*weeks+days]
                Due=`AddToDate $Month/$Day/$Year $days`
          ;;
          *d )    # Like 5 days or 5d
                ExtensionExp=`echo $ExtensionExp | sed 's/[a-z]/ /g'`
                days=$ExtensionExp
                Due=`AddToDate $Month/$Day/$Year $days`
          ;;
          * )
                Due=$ExtensionExp
          ;;
       esac
       echo $Due
    
    }
    
    
    # Pop -- remove the first element from an array and shift left
    Pop () {
       Var=$1
       eval "unset $Var[0]"
       eval "$Var=(\${$Var[*]})"
    }
    
    ComputeDate () {
       local Date=`NormalizeDate $1`; shift
       local Expression=`echo $* | sed 's/^ *a /1 /;s/,/ /' | tr A-Z a-z `
       local Exp=(`echo $Expression `)
       local Token=$Exp  # first one
       local Ans=
       #echo "Computing date for ${Exp[*]}" > /dev/tty
       case $Token in
          */* ) # Regular date
             M=`GetMonth $Token`
             D=`GetDay $Token`
             Y=`GetYear $Token`
             if [ -z "$Y" ]; then
                Y=$Year
             elif [ ${#Y} -eq 2 ]; then
                Y=20$Y
             fi
             Ans="$M/$D/$Y"
             ;;
          yes* )
             Ans=`AddToDate $Date -1`
             ;;
          tod*|now )
             Ans=$Date
             ;;
          tom* )
             Ans=`AddToDate $Date 1`
             ;;
          the )
             case $Expression in
                *day*after* )  #the day after Date
                   Pop Exp;   # Skip the
                   Pop Exp;   # Skip day
                   Pop Exp;   # Skip after
                   #echo Calling ComputeDate $Date ${Exp[*]} > /dev/tty
                   Date=`ComputeDate $Date ${Exp[*]}` #Recursive call
                   #echo "New date is " $Date > /dev/tty
                   Ans=`AddToDate $Date 1`
                   ;;
                *last*day*of*th*month|*end*of*th*month )
                   M=`date +%m`
                   Day=${Months[M-1]}
                   if [ $M -eq 2 -a `IsLeapYear $Year` = yes ]; then
                      let Day++
                   fi
                   Ans=$Month/$Day/$Year
                   ;;
                *last*day*of* )
                   D=${Expression##*of }
                   D=`NormalizeDate $D`
                   M=`GetMonth $D`
                   Y=`GetYear $D`
                   # echo M is $M > /dev/tty
                   Day=${Months[M-1]}
                   if [ $M -eq 2 -a `IsLeapYear $Y` = yes ]; then
                      let Day++
                   fi
                   Ans=$[M]/$Day/$Y
                   ;;
                * )
                   echo "Unknown expression: " $Expression
                   exit
                   ;;
             esac
             ;;
          next* ) # next DayOfWeek
             Pop Exp
             dow=`Day2Int $DayOfWeek` # First 3 chars
             tdow=`Day2Int ${Exp:0:3}` # First 3 chars
             n=$[7-dow+tdow]
             Ans=`AddToDate $Date $n`
             ;;
          this* )
             Pop Exp
             dow=`Day2Int $DayOfWeek`
             tdow=`Day2Int ${Exp:0:3}` # First 3 chars
             if [ $dow -gt $tdow ]; then
                echo "'this $Exp' has passed.  Did you mean 'next $Exp?'"
                exit
             fi
             n=$[tdow-dow]
             Ans=`AddToDate $Date $n`
             ;;
          [a-z]* ) # DayOfWeek ...
    
             M=${Exp:0:3}
             case $M in
                jan|feb|mar|apr|may|june|jul|aug|sep|oct|nov|dec )
                   ND=`NormalizeDate ${Exp[*]}`
                   Ans=$ND
                   ;;
                mon|tue|wed|thu|fri|sat|sun )
                   dow=`Day2Int $DayOfWeek`
                   Ans=`NormalizeDate $Exp`
    
                   if [ ${#Exp[*]} -gt 1 ]; then # Just a DayOfWeek
                      #tdow=`GetDay $Exp` # First 3 chars
                      #if [ $dow -gt $tdow ]; then
                         #echo "'this $Exp' has passed.  Did you mean 'next $Exp'?"
                         #exit
                      #fi
                      #n=$[tdow-dow]
                   #else  # DayOfWeek in a future week
                      Pop Exp  # toss monday
                      Pop Exp  # toss in/off
                      if [ $Exp = next ]; then
                         Exp=2
                      fi
                      n=$[7*(Exp-1)]   # number of weeks
                      n=$[n+7-dow+tdow]
                      Ans=`AddToDate $Date $n`
                   fi
                   ;;
             esac
             ;;
          [0-9]* ) # Number  weeks [from|after] Date
             n=$Exp
             Pop Exp;
             case $Exp in
                w* ) let n=7*n;;
             esac
    
             Pop Exp; Pop Exp
             #echo Calling ComputeDate $Date ${Exp[*]} > /dev/tty
             Date=`ComputeDate $Date ${Exp[*]}` #Recursive call
             #echo "New date is " $Date > /dev/tty
             Ans=`AddToDate $Date $n`
             ;;
       esac
       echo $Ans
    }
    
    Year=`date +%Y`
    Month=`date +%m`
    Day=`date +%d`
    DayOfWeek=`date +%a |tr A-Z a-z`
    
    Date="$Month/$Day/$Year"
    ComputeDate $Date $*
     

    Dieses Skript macht Gebrauch von einem anderen Skript, das ich geschrieben habe col ... viele entschuldigen sich bei denjenigen, die den Standard verwenden, der in Linux enthalten ist. Diese Version von col vereinfacht das Extrahieren von Spalten aus dem Standardeintrag.

     $ echo a b c d e | col 5 3 2
     

    druckt

     e c b
     

    Hier das Skript col :

     #!/bin/sh
    # col -- extract columns from a file
    # Usage:
    #    col [-r] [c] col-1 col-2 ...
    #   where [c] if supplied defines the field separator
    #   where each col-i represents a column interpreted according to  the presence of -r as follows:
    #        -r present : counting starts from the right end of the line
    #        -r absent  : counting starts from the left side of the line
    Separator=" "
    Reverse=false
    case "$1" in
     -r )  Reverse=true; shift;
     ;;
     [0-9]* )
     ;;
     * )Separator="$1"; shift;
     ;;
    esac
    
    case "$1" in
     -r )  Reverse=true; shift;
     ;;
     [0-9]* )
     ;;
     * )Separator="$1"; shift;
     ;;
    esac
    
    #  Replace each col-i with $i
    Cols=""
    for  f in $*
    do
      if [ $Reverse = true ]; then
         Cols="$Cols \$(NF-$f+1),"
      else
         Cols="$Cols \$$f,"
      fi
    
    done
    
    Cols=`echo "$Cols" | sed 's/,$//'`
    #echo "Using column specifications of $Cols"
    awk -F "$Separator"  "{print $Cols}"
     

    Außerdem wird printdirections zum Ausdrucken von Anweisungen verwendet, wenn das Skript nicht ordnungsgemäß aufgerufen wird:

     #!/bin/sh
    #
    #  printdirections -- print header lines of a shell script
    #
    #  Usage:
    #      printdirections path
    #  where
    #      path is a *full* path to the shell script in question
    #      beginning with '/'
    #
    #  To use printdirections, you must include (as comments at the top
    #  of your shell script) documentation for running the shell script.
    
    if [ $# -eq 0 -o "$*" = "-h" ]; then
       printdirections $0
       exit
    fi
    #  Delete the command invocation at the top of the file, if any
    #  Delete from the place where printdirections occurs to the end of the file
    #  Remove the # comments
    #  There is a bizarre oddity here.
       sed '/#!/d;/.*printdirections/,$d;/ *#/!d;s/# //;s/#//' $1 > /tmp/printdirections.$$
    
    #  Count the number of lines
    numlines=`wc -l /tmp/printdirections.$$ | awk '{print $1}'`
    
    #  Remove the last   line
    numlines=`expr $numlines - 1`
    
    
    head -n $numlines /tmp/printdirections.$$
    rm /tmp/printdirections.$$
     

    Um diese Stelle zu verwenden, verwenden Sie die drei Skripts in den Dateien ComputeDate , col und printdirections . Legen Sie die Datei in ein Verzeichnis, das von PATH benannt wird, normalerweise ~ / bin. Dann machen Sie sie ausführbar mit:

     $ chmod a+x ComputeDate col printdirections
     

    Probleme? Senden Sie mir ein paar E-Mails: morell AT cs.atu.edu Platzieren Sie ComputeDate im Betreff.

    26 June 2010
    Larry Morell
  • Für die BSD / OS X-Kompatibilität können Sie das Datums-Dienstprogramm auch mit -j und -v verwenden, um Datumsberechnungen durchzuführen. Auf der FreeBSD-Manpage finden Sie das Datum . Sie können die vorherigen Linux-Antworten mit dieser Antwort kombinieren, um eine ausreichende Kompatibilität zu gewährleisten.

    Unter BSD erhalten Sie als Linux bei Ausführung von date das aktuelle Datum:

     $ date
    Wed 12 Nov 2014 13:36:00 AEDT
     

    Nun können Sie mit dem BSD-Datum mit -v rechnen, z. B. das Datum von morgen (+1d ist plus einen Tag ):

     $ date -v +1d
    Thu 13 Nov 2014 13:36:34 AEDT
     

    Sie können ein vorhandenes Datum als Basis verwenden , und geben Sie optional das Analyseformat mit strftime an. Stellen Sie sicher, dass Sie -j verwenden, um das Systemdatum nicht zu ändern:

     $ date -j -f "%a %b %d %H:%M:%S %Y %z" "Sat Aug 09 13:37:14 2014 +1100"
    Sat  9 Aug 2014 12:37:14 AEST
     

    Und Sie können dies als Grundlage für Datumsberechnungen verwenden:

     $ date -v +1d -f "%a %b %d %H:%M:%S %Y %z" "Sat Aug 09 13:37:14 2014 +1100"
    Sun 10 Aug 2014 12:37:14 AEST
     

    Beachten Sie das -v impliziert -j.

    Es können mehrere Anpassungen nacheinander vorgenommen werden:

     $ date -v +1m -v -1w
    Fri  5 Dec 2014 13:40:07 AEDT
     

    Weitere Informationen finden Sie in der Manpage.

    12 November 2014
    sj26
  • Um Datumsangaben unter UNIX zu berechnen, erhalten Sie das Datum als Anzahl Sekunden seit der UNIX-Epoche. Führen Sie einige Berechnungen durch und konvertieren Sie sie anschließend wieder in Ihr druckbares Datumsformat. Mit dem Date-Befehl können Sie sowohl die Sekunden seit der Epoche angeben als auch von dieser Zahl in ein druckbares Datum zurückwandeln. Mein lokaler Datumsbefehl führt dies aus.

     % date -n
    1219371462
    % date 1219371462
    Thu Aug 21 22:17:42 EDT 2008
    % 
     

    Siehe Ihre lokale Manpage date(1). Um zu erhöhen Ein Tag addiert 86400 Sekunden.

    24 November 2009
    abyx
  •  date --date='1 days ago' '+%a'
     

    Dies ist keine sehr kompatible Lösung. Es funktioniert nur unter Linux. Zumindest hat es in Aix und Solaris nicht funktioniert.

    Es funktioniert in RHEL:

     date --date='1 days ago' '+%Y%m%d'
    20080807
     
    05 September 2014
    jaypal singh
  • Warum schreiben Sie Ihre Skripts nicht in einer Sprache wie Perl oder Python, die natürlicherweise die komplexe Datumsverarbeitung unterstützt? Natürlich können Sie alles in bash erledigen, aber ich denke, dass Sie auch plattformübergreifend mehr Konsistenz mit Python erhalten, solange Sie sicherstellen, dass Perl oder Python installiert ist |>

    Ich sollte hinzufügen, dass es sehr einfach ist, Python- und Perl-Skripts zu einem Shell-Skript zu verbinden.

    09 August 2008
    Justin Standard
  • Ich bin ein paar Mal darauf gestoßen. Meine Gedanken sind:

    1. Datumsberechnung ist immer ein Schmerz
    2. Bei Verwendung des EPOCH-Datumsformats
    3. Datum konvertiert unter Linux in EPOCH, jedoch nicht unter Solaris
    4. Für eine tragbare Lösung müssen Sie einen der folgenden Schritte ausführen:
      1. Installieren Sie gnu date auf solaris (bereits erwähnt, zur Interaktion mit Menschen erforderlich)
      2. Verwenden Sie perl für das Datum part ( die meisten Unix-Installationen enthalten perl, daher würde ich im Allgemeinen annehmen, dass diese Aktion nicht zusätzliche Arbeit erfordert).

    Ein Beispielskript (prüft auf das Alter bestimmter Benutzerdateien, ob das Konto gelöscht werden kann):

     #!/usr/local/bin/perl
    
    $today = time();
    
    $user = $ARGV[0];
    
    $command="awk -F: '/$user/ {print \$6}' /etc/passwd";
    
    chomp ($user_dir = `$command`);
    
    if ( -f "$user_dir/.sh_history" ) {
        @file_dates   = stat("$user_dir/.sh_history");
        $sh_file_date = $file_dates[8];
    } else {
        $sh_file_date = 0;
    }
    if ( -f "$user_dir/.bash_history" ) {
        @file_dates     = stat("$user_dir/.bash_history");
        $bash_file_date = $file_dates[8];
    } else {
        $bash_file_date = 0;
    }
    if ( $sh_file_date > $bash_file_date ) {
        $file_date = $sh_file_date;
    } else {
        $file_date = $bash_file_date;
    }
    $difference = $today - $file_date;
    
    if ( $difference >= 3888000 ) {
        print "User needs to be disabled, 45 days old or older!\n";
        exit (1);
    } else {
        print "OK\n";
        exit (0);
    }
     
    16 September 2008
    Jonathan Bourke
  • Wenn Sie sich das näher anschauen, können Sie einfach date verwenden. Ich habe Folgendes unter OpenBSD ausprobiert: Ich habe das Datum vom 29. Februar 2008 und eine zufällige Stunde (in Form von 080229301535) genommen ) und fügte +1 zum Tag hinzu, wie folgt:

     $ date -j 0802301535
    Sat Mar  1 15:35:00 EST 2008
     

    Wie Sie sehen, formatiert das Datum Zeit richtig ...

    HTH

    09 August 2008
    abyx
  • Wenn Sie mit awk fortfahren möchten, sind die Funktionen mktime und strftime hilfreich:

     
    BEGIN { dateinit }
          { newdate=daysadd(OldDate,DaysToAdd)}
    
     # daynum: convert DD-MON-YYYY to day count
     #-----------------------------------------
    function daynum(date,  d,m,y,i,n)
    {
         y=substr(date,8,4)
         m=gmonths[toupper(substr(date,4,3))]
         d=substr(date,1,2)
         return mktime(y" "m" "d" 12 00 00")
    }
    
     #numday: convert day count to DD-MON-YYYY
     #-------------------------------------------
    function numday(n,  y,m,d)
    {
        m=toupper(substr(strftime("%B",n),1,3))
        return strftime("%d-"m"-%Y",n)
    }
    
     # daysadd: add (or subtract) days from date (DD-MON-YYYY), return new date (DD-MON-YYYY)
     #------------------------------------------
    function daysadd(date, days)
    {
        return numday(daynum(date)+(days*86400))
    }
    
     #init variables for date calcs
     #-----------------------------------------
    function dateinit(   x,y,z)
    {
         # Stuff for date calcs
         split("JAN:1,FEB:2,MAR:3,APR:4,MAY:5,JUN:6,JUL:7,AUG:8,SEP:9,OCT:10,NOV:11,DEC:12", z)
         for (x in z)
         {
            split(z[x],y,":")
            gmonths[y[1]]=y[2]
         }
    }
     
    16 September 2008
    Joe Watkins