В оболочке unix, как получить вчерашнюю дату в переменную?

У меня есть сценарий оболочки, который делает следующее для сохранения даты текущего дня в переменной «dt»:

date "+%a %d/%m/%Y" | read dt
echo ${dt}

Как мне получить дату вчера в переменную?

В основном то, чего я пытаюсь добиться, - это использовать grep для извлечения всех вчерашних строк из файла журнала, поскольку каждая строка в журнале содержит дату в формате «Mon 01/02/2010».

Большое спасибо


person Chris    schedule 19.08.2010    source источник
comment
Perl - это вариант, если это необходимо...   -  person Chris    schedule 19.08.2010


Ответы (17)


Если у вас есть доступный Perl (и ваш date не имеет приятных функций, таких как yesterday), вы можете использовать:

pax> date
Thu Aug 18 19:29:49 XYZ 2010

pax> dt=$(perl -e 'use POSIX;print strftime "%d/%m/%Y%",localtime time-86400;')

pax> echo $dt
17/08/2010
person paxdiablo    schedule 19.08.2010
comment
@Chris: обратите внимание, что это дает вам дату 24 часа назад, которая немного отличается от вчерашней даты. Если в вашем регионе используется летнее время, это даст неправильную дату после 23:00 в первый день зимнего времени. - person Gilles 'SO- stop being evil'; 19.08.2010
comment
@ Жиль, это неплохой момент, так как я использую locattime. Если вас это беспокоит, вы можете проверить, больше ли час, чем 6 вечера, просто вычтите 6 часов. Надеюсь, это должно покрыть это. - person paxdiablo; 19.08.2010
comment
Хороший вопрос, Жиль. Я скучаю по C# ‹sob›: DateTime.Now.AddDays(-1) - person Chris; 20.08.2010
comment
brew install coreutils устанавливает дату gnu как gdate. Работает на macOS и Linux. - person HappyFace; 08.05.2020

В Linux вы можете использовать

date -d "-1 days" +"%a %d/%m/%Y"
person z1x2    schedule 19.08.2010
comment
Это лучший ответ среди всех остальных, короткий, милый, легкий, удобный, крутой, и он доказывает историю «Дай человеку рыбу, он сыт на день, но научи его ловить рыбу, он сыт на всю жизнь». - person mtk; 20.03.2015
comment
Примечание для пользователей AIX: к сожалению, флаг -d не поддерживается для date. - person Davy M; 06.06.2017
comment
Спасибо. Это помогло. - person Kanav Narula; 20.08.2018

Вы можете использовать команду даты GNU, как показано ниже

Получение даты в прошлом

Чтобы получить вчерашний и более ранний день в прошлом, используйте строку day ago:

дата --date='вчера'

date --date='1 день назад'

дата --date='10 дней назад'

date --date='10 недель назад'

date --date='10 месяцев назад'

дата --date='10 лет назад'

Получение даты в будущем

Чтобы получить завтра и послезавтра (завтра+N), используйте слово дня, чтобы получить дату в будущем следующим образом:

дата --date='завтра'

дата --date='1 день'

дата --date='10 день'

дата --date='10 неделя'

дата --date='10 месяцев'

дата --date='10 лет'

person ramit girdhar    schedule 08.09.2015

Если вы используете Mac, BSD или что-то еще без параметра --date, вы можете использовать:

date -r `expr \`date +%s\` - 86400` '+%a %d/%m/%Y'

Обновление: или, возможно...

date -r $((`date +%s` - 86400)) '+%a %d/%m/%Y'
person DigitalRoss    schedule 19.08.2010
comment
Было бы менее неудобно использовать $() вместо `. кш имеет $()? - person bstpierre; 19.08.2010
comment
+1 только за то, что не предполагал, что каждый вопрос UNIX касается Linux. Некоторым из нас приходится работать и с другими стилями. - person paxdiablo; 19.08.2010
comment
@paxdiablo: согласен, но если конкретная информация не указана, то я лично предполагаю, что инструментарий GNU является вариантом;) Различия между HP-UX, AIX, Solaris и *BSD просто слишком велики, чтобы угадать вкус. - person Wolph; 19.08.2010
comment
Может ли это потерпеть неудачу в странных угловых случаях? Например, когда есть дополнительная секунда? - person Alok Singhal; 19.08.2010
comment
@Alok: POSIX/Unix не отслеживает високосные секунды (все дни составляют 86400 секунд), но есть крайний случай с летним временем (см. мой комментарий на ответ paxdiablo - person Gilles 'SO- stop being evil'; 19.08.2010
comment
@DigitalRoss: К сожалению, date +%s тоже не POSIX, хотя он более доступен, чем --date yesterday. - person Gilles 'SO- stop being evil'; 19.08.2010

У меня есть сценарий оболочки в Linux, и у меня работал следующий код:

#!/bin/bash
yesterday=`TZ=EST+24 date +%Y%m%d` # Yesterday is a variable
mkdir $yesterday # creates a directory with  YYYYMMDD format
person jujuBee    schedule 11.06.2014
comment
TZ — часовой пояс, EST+24 — вчерашняя дата по восточному поясному времени (также можно использовать EST-24 для завтрашней даты) +%Y%m%d — формат ГГГГММДД. - person jujuBee; 10.06.2015
comment
Это, безусловно, самая краткая версия, которая работает в AIX для всех, кто ищет такой ответ. AIX не поддерживает флаги -r или -d, но фактически позволяет управлять часовым поясом вот так! Вы сделали мой день. Я пытался понять это около двух часов, я делаю дату полугодовой давности, а другие идеи не сработали. - person Davy M; 06.06.2017

У вас есть как минимум 2 варианта

  1. Используйте перл:

    perl -e '@T=localtime(time-86400);printf("%02d/%02d/%02d",$T[4]+1,$T[3],$T[5]+1900)'
    
  2. Установите дату GNU (она находится в пакете sh_utils, если я правильно помню)

    date --date yesterday "+%a %d/%m/%Y" | read dt
    echo ${dt}
    
  3. Не уверен, что это работает, но вы можете использовать отрицательный часовой пояс. Если вы используете часовой пояс на 24 часа раньше вашего текущего часового пояса, вы можете просто использовать date.

person Wolph    schedule 19.08.2010
comment
@Chris: Я предполагал, что это не будет GNU-совместимый date, но, поскольку вы не указали вариант Unix, я просто догадался;) С HP-UX ваши возможности немного более ограничены, date не имеет этих параметров, поэтому Perl может быть лучший вариант. - person Wolph; 19.08.2010
comment
Не то чтобы это имело значение, но вам не нужно добавлять 1900 к году, если вы собираетесь %100 получить результат :-) - person paxdiablo; 19.08.2010
comment
@paxdiablo: справедливое замечание, Perl, очевидно, не входит в число моих сильных сторон;) Вместо этого я поставлю +1 к вашему ответу. - person Wolph; 19.08.2010

Попробуйте следующий метод:

dt=`case "$OSTYPE" in darwin*) date -v-1d "+%s"; ;; *) date -d "1 days ago" "+%s"; esac`
echo $dt

Он работает как на Linux, так и на OSX.

person kenorb    schedule 15.05.2014

Вот сценарий ksh для вычисления предыдущей даты первого аргумента, проверенный на Solaris 10.

#!/bin/ksh
 sep=""
 today=$(date '+%Y%m%d')
 today=${1:-today}
 ty=`echo $today|cut -b1-4` # today year
 tm=`echo $today|cut -b5-6` # today month
 td=`echo $today|cut -b7-8` # today day
 yy=0 # yesterday year
 ym=0 # yesterday month
 yd=0 # yesterday day

 if [ td -gt 1 ];
 then
         # today is not first of month
         let yy=ty       # same year
         let ym=tm       # same month
         let yd=td-1     # previous day
 else
         # today is first of month
         if [ tm -gt 1 ];
         then
                 # today is not first of year
                 let yy=ty       # same year
                 let ym=tm-1     # previous month
                 if [ ym -eq 1 -o ym -eq 3 -o ym -eq 5 -o ym -eq 7 -o ym -eq 8 -o ym -     eq 10 -o ym -eq 12 ];
                 then
                         let yd=31
                 fi
                 if [ ym -eq 4 -o ym -eq 6 -o ym -eq 9 -o ym -eq 11 ];
                 then
                         let yd=30
                 fi
                 if [ ym -eq 2 ];
                 then
                         # shit... :)
                         if [ ty%4 -eq 0 ];
                         then
                                 if [ ty%100 -eq 0 ];
                                 then
                                         if [ ty%400 -eq 0 ];
                                         then
                                         #echo divisible by 4, by 100, by 400
                                                 leap=1 
                                         else
                                         #echo divisible by 4, by 100, not by 400
                                                 leap=0
                                         fi
                                 else
                                         #echo divisible by 4, not by 100
                                         leap=1 
                                 fi
                         else
                                 #echo not divisible by 4
                                 leap=0 # not divisible by four
                         fi
                         let yd=28+leap
                 fi
         else
                 # today is first of year
                 # yesterday was 31-12-yy
                 let yy=ty-1     # previous year
                 let ym=12
                 let yd=31
         fi
 fi
 printf "%4d${sep}%02d${sep}%02d\n" $yy $ym $yd

Тесты

bin$ for date in 20110902 20110901 20110812 20110801 20110301 20100301 20080301 21000301 20000301 20000101 ; do yesterday $date; done
20110901
20110831
20110811
20110731
20110228
20100228
20080229
21000228
20000229
19991231
person Jose Manuel Gomez Alvarez    schedule 02.09.2011

Спасибо всем за помощь, но так как я на HP-UX (в конце концов: чем больше вы платите, тем меньше функций вы получаете...), мне пришлось прибегнуть к perl:

perl -e '@T=localtime(time-86400);printf("%02d/%02d/%04d",$T[3],$T[4]+1,$T[5]+1900)' | read dt
person Chris    schedule 19.08.2010

Если в вашей установке HP-UX установлен Tcl, вы можете найти его арифметику дат очень удобочитаемой (к сожалению, в оболочке Tcl нет хорошей опции «-e», как в perl):

dt=$(echo 'puts [clock format [clock scan yesterday] -format "%a %d/%m/%Y"]' | tclsh)
echo "yesterday was $dt"

Это справится со всеми проблемами, связанными с переходом на летнее время.

person glenn jackman    schedule 19.08.2010

Если у вас нет версии date, поддерживающей --yesterday, и вы не хотите использовать perl, вы можете использовать этот мой удобный скрипт ksh. По умолчанию он возвращает вчерашнюю дату, но вы можете передать ему число, и он сообщит вам дату, которая прошла много дней назад. Он начинает немного замедляться, если вы смотрите далеко в прошлое. 100 000 дней назад это было 30 января 1738 года, хотя моей системе потребовалось 28 секунд, чтобы понять это.

    #! /bin/ksh -p

    t=`date +%j`
    ago=$1
    ago=${ago:=1} # in days
    y=`date +%Y`

    function build_year {
            set -A j X $( for m in 01 02 03 04 05 06 07 08 09 10 11 12
                    {
                            cal $m $y | sed -e '1,2d' -e 's/^/ /' -e "s/ \([0-9]\)/ $m\/\1/g"
                    } )
            yeardays=$(( ${#j[*]} - 1 ))
    }

    build_year

    until [ $ago -lt $t ]
    do
            (( y=y-1 ))
            build_year
            (( ago = ago - t ))
            t=$yeardays
    done

    print ${j[$(( t - ago ))]}/$y
person Ken Beer    schedule 26.11.2010

кш93:

dt=${ printf "%(%a %d/%m/%Y)T" yesterday; }

or:

dt=$(printf "%(%a %d/%m/%Y)T" yesterday)

Первый работает в том же процессе, второй — в подоболочке.

person danlei    schedule 31.01.2013
comment
@clarkw: Хорошее предложение, я добавлю его к ответу. - person danlei; 15.03.2013

Для Hp-UX у меня работала только следующая команда:

TZ=aaa24 дата +%Y%m%d

вы можете использовать его как:

ydate=`TZ=aaa24 дата +%Y%m%d`

эхо $ydate

person Anvesh    schedule 07.08.2013

Если у вас есть доступ к python, это помощник, который получит значение даты yyyy-mm-dd для любого произвольного n дня назад:

function get_n_days_ago {
  local days=$1
  python -c "import datetime; print (datetime.date.today() - datetime.timedelta(${days})).isoformat()"
}

# today is 2014-08-24

$ get_n_days_ago 1
2014-08-23

$ get_n_days_ago 2
2014-08-22
person wuster    schedule 25.08.2014

$var=$TZ;
TZ=$TZ+24;
date;
TZ=$var;

Получите вас вчера в AIX и верните переменную TZ обратно в исходное состояние.

person santymano    schedule 18.05.2015

Хотя все хорошие ответы, к сожалению, ни один из них не сработал для меня. Поэтому мне пришлось написать что-то старомодное. (у меня была минимальная ОС Linux)

$ date -d @$( echo $(( $(date +%s)-$((60*60*24)) )) )

Вы можете комбинировать это с обычным форматированием даты. Например.

$ date -d @$( echo $(( $(date +%s)-$((60*60*24)) )) ) +%Y-%m-%d

Объяснение: введите дату в секундах эпохи (опция -d), из которых вы бы вычли секунды, эквивалентные одному дню. Это даст дату ровно на один день назад.

person Gautam    schedule 07.04.2018

person    schedule
comment
+1 за точный ответ на вопрос. Предостережение в том, что флаг -yesterday может не поддерживаться в версии unix для постеров. - person James Anderson; 19.08.2010
comment
-d вчера для краткого синтаксиса. - person COil; 26.07.2016