Как работает опция «1 месяц назад» в команде date?

22

Я не уверен, получает ли это прошлую дату в течение текущего дня, или это займет всего 30 или 31 день.

например

Если текущая дата - March 28th1 месяц назад February 28th, то что же произойдет, когда это произойдет March 30th?

сценарий

Я хочу делать резервные копии некоторых файлов каждый день, скрипт будет сохранять эти файлы в пределах текущей даты в $(date +%Y%m%d)формате, например 20150603_bckp.tar.gz, затем, когда наступит следующий месяц, удалите все эти файлы в течение 1 месяца назад, кроме файлов 1-го и 15-го, так что это мое состояние:

past_month = $(date -d "-1 month" +%Y%m%d)
day = $(date +%d)
if [ "$day" != 01 ] && [ "$day" != 15 ]
then
    rm /path/of/files/${past_month}_bckp.tar.gz
    echo "Depuration done"
else
    echo "Keep file"
fi

Но я хочу знать, что произойдет, когда дата будет 30, 31 или даже в прошлом феврале? Это будет держать эти файлы? или удалить файлы первого дня?

Когда он будет 31-го, будет выполняться удаление, поэтому, если в прошлом месяце было только 30 дней, это удалит файл первого дня?

Надеюсь, я намекнул.

tachomi
источник
1
Разве вы не знаете, что я здесь 30 марта именно по этой причине
user7203

Ответы:

24

- 1 monthвычтет единицу из номера месяца, а затем, если полученная дата недействительна ( February 30например,), скорректируйте ее так, чтобы она была действительной. Так и December 31 - 1 monthесть December 1, не ноябрьский день, а March 31 - 1 monthесть March 3(если не выполнено в високосный год).

Вот цитата со страницы информации для Gnu date(это dateверсия, которая реализует этот синтаксис), которая включает в себя хорошее предложение, чтобы сделать арифметику более устойчивой:

Пух в единицах может вызвать проблемы с относительными элементами. Например, 2003-07-31 -1 monthможет иметь значение 2003-07-01, потому что 2003-06-31 является недопустимой датой. Чтобы более точно определить предыдущий месяц, вы можете запросить месяц до 15-го числа текущего месяца. Например:

    $ date -R
    Thu, 31 Jul 2003 13:02:39 -0700
    $ date --date='-1 month' +'Last month was %B?'
    Last month was July?
    $ date --date="$(date +%Y-%m-15) -1 month" +'Last month was %B!'
    Last month was June!

Еще одно предупреждение, также цитируемое на информационной странице:

Кроме того, будьте осторожны при манипулировании датами с изменениями часов, такими как переходы на летнее время. В некоторых случаях они прибавляют или вычитают до 24 часов от часов, поэтому часто целесообразно использовать универсальное время, установив для TZпеременной среды значение, UTC0 прежде чем приступать к календарным вычислениям.

RICi
источник
У меня есть сомнения здесь, особенно в февральской ситуации ... Когда это 29, 30 или 31 марта, это может занять следующее число прошлого месяца, если текущий не существует, так что в этих трех ситуациях это может занять 1 марта нет? Потому что если 29, 30, 31, а затем 1, 2, 3 марта, как вы сказали, то 1 апреля будет 4 марта из-за реструктуризации (я не знаю, хорошо ли это сказано), которая была сделана, что вы думаете ?
Тачоми
Один месяц до 1 апреля - 1 марта, а один месяц до 1 марта - 1 февраля. Это не проблемы. Проблема в том, что один месяц до 31 мая - 1 мая, потому что 31 апреля не существует. Вам следует проверить номер дня, который был указан месяц назад, а не день текущей даты.
Ричи
2
Doh! Тот факт, что «один месяц назад» некоторых конкретных дней в любом месяце может привести к тому же самому месяцу, - это то, чего я не ожидал от dateреализации; в моей книге это семантически нелогично. - Спасибо за указание на это, это приятно знать.
Янис
2

Вместо того чтобы полагаться на имена файлов для очистки файлов резервных копий, вам будет безопаснее полагаться на их метаданные времени.

Например, вы можете удалить все файлы старше 30 дней с помощью этой команды:

/usr/bin/find /path/to/your/files -type f -ctime +30 -delete

В качестве бесплатного бонуса ежедневная работа позволит вам хранить файлы резервных копий в непрерывном месяце, что позволит лучше управлять дисковым пространством.

Для хранения 1-го или 15-го файлов вы можете либо сохранить их в другом каталоге, либо обновить команду find с параметром -not -name.

Бертран Лупарт
источник
0

Вы можете попытаться увидеть, как работает дата, следующим образом:

date -d "$(date -d "Mar 31 2019" +%F) +1 month ago"
Sun Mar  3 00:00:00 EET 2019

Поэтому я думаю, что, исходя из текущего месяца в прошлом месяце (не текущего, если это март), уменьшается количество дней с последнего месяца по сравнению с текущим месяцем.

Вы можете использовать следующий синтаксис для удаления файлов старше нескольких дней (в примере ниже 31 день). Одна строка для решения проблемы (это для простого подхода).

find /path/to/folder/with/arhives/ -mindepth 1 -mtime +31 -delete

Для более детального подхода вы также можете сделать что-то вроде этого: 1. Найти количество дней для текущего месяца:

cal $(date +%m) $(date +%y) | egrep -v "$(date +%y)|Su" | xargs | awk '{print $NF}'
  1. Нахождение количества дней за последний месяц:

    echo "$ (cal $ (date +% m) $ (date +% y) | egrep -v" $ (date +% y) | Su "| xargs | awk '{print $ NF}') -" $ ( cal $ (date -d "+1 месяц назад" +% m) $ (date +% y) | egrep -v "$ (date +% y) | Su" | xargs | awk '{print $ NF}') | До нашей эры

  2. Итак, теперь мы находим разницу между этими двумя месяцами:

    echo "$ (cal $ (date +% m) $ (date +% y) | egrep -v" $ (date +% y) | Su "| xargs | awk '{print $ NF}') -" $ ( cal $ (date -d "+1 месяц назад" +% m) $ (date +% y) | egrep -v "$ (date +% y) | Su" | xargs | awk '{print $ NF}') | До нашей эры

Теперь давайте назначим некоторые переменные этим 3 шагам. Шаг 1 Имя переменной: FCM Шаг 2 Имя переменной: FLM Шаг 3 Переменная NAme: DCL

FCM=$(cal $(date +%m) $(date +%y) | egrep -v "$(date +%y)|Su" | xargs | awk '{print $NF}')
FLM=$(al $(date -d "+1 month ago" +%m) $(date +%y) | egrep -v "$(date +%y)|Su" | xargs | awk '{print $NF}')
DCL=$(echo "$FCM-$FLM" | bc)

Проверьте, равен ли $ DCL 0 (ноль), и удалите, основываясь на разнице между $ FCM и $ FLM:

if [ $DCL -ne 0 ]; then
    if [ $DCL -lt 0 ]; then
        find /path/to/folder/with/arhives/ -mindepth 1 -mtime +$(echo "$DCL+$FLM" | bc) -delete
    elif [ $DCL -gt 0 ]; then
        find /path/to/folder/with/arhives/ -mindepth 1 -mtime +$(echo "$DCL+$FLM" | bc) -delete
    fi
else
    find /path/to/folder/with/arhives/ -mindepth 1 -mtime +$FLM -delete
fi

Вы также можете добавить переменную в «/ path / to / folde / with / arhives /».

Вывод: если вы хотите удалить файлы старше одного месяца (ровно), вам нужно отрегулировать точное количество дней, если вы используете команду «дата» и «+1 месяц назад».

Михай М
источник