Jak działa opcja „1 miesiąc temu” w poleceniu daty?


22

Nie jestem pewien, czy ta data minie w ciągu bieżącego dnia, czy też zajmie to tylko 30 lub 31 dni.

na przykład

Jeśli aktualna data to March 28th1 miesiąc, musi być February 28th, ale co się stanie, kiedy będzie March 30th?

Scenariusz

Chcę tworzyć kopie zapasowe niektórych plików każdego dnia, skrypt zapisze te pliki w bieżącej dacie w $(date +%Y%m%d)formacie, np. 20150603_bckp.tar.gzKiedy nadejdzie następny miesiąc, usuń wszystkie te pliki w ciągu 1 miesiąca z wyjątkiem plików 1. i 15., więc jest to moja kondycja:

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

Ale chcę wiedzieć, co się stanie, gdy data przypada na 30, 31, a nawet ostatni przykład z lutego? Zachowa te pliki? lub usunąć pliki pierwszego dnia?

Kiedy będzie 31. wydalanie zostanie wykonane, więc jeśli miniony miesiąc miał tylko 30 dni, spowoduje to usunięcie pliku pierwszego dnia?

Mam nadzieję, że podpowiedziałem.


1
Czy nie wiesz, że jestem tutaj 30 marca z tego właśnie powodu
7203

Odpowiedzi:


24

- 1 monthodejmie jeden od numeru miesiąca, a następnie, jeśli wynikowa data jest niepoprawna ( February 30na przykład), dostosuj ją, aby była poprawna. Tak December 31 - 1 monthjest December 1, nie ma dnia, w listopadzie, a March 31 - 1 monthjest March 3(chyba stracony w roku przestępnym).

Oto cytat ze strony informacyjnej Gnu date(która jest datewersją, która implementuje tę składnię), która zawiera dobrą sugestię, aby uczynić arytmetykę bardziej niezawodną:

Fuzz w jednostkach może powodować problemy z względnymi przedmiotami. Na przykład 2003-07-31 -1 monthmoże to być 2003-07-01, ponieważ 2003-06-31 jest niepoprawną datą. Aby bardziej wiarygodnie określić poprzedni miesiąc, możesz poprosić o miesiąc przed 15 dniem bieżącego miesiąca. Na przykład:

    $ 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!

Kolejne ostrzeżenie, również cytowane ze strony informacyjnej:

Zachowaj także ostrożność podczas manipulowania datami w trakcie zmian zegara, takich jak skoki czasu letniego. W kilku przypadkach dodawano lub odejmowano nawet 24 godziny od zegara, więc często rozsądnie jest przyjąć czas uniwersalny, ustawiając TZzmienną środowiskową UTC0 przed rozpoczęciem obliczeń kalendarzowych.


Mam tutaj wątpliwości, szczególnie w sytuacji lutowej ... Kiedy jest 29, 30 lub 31 marca, może minąć następująca liczba z ostatniego miesiąca, jeśli obecny nie istnieje, więc w tych trzech sytuacjach może to zająć 1 marca nie? Bo jeśli 29, 30, 31 marca, a następnie 1, 2, 3 marca, jak powiedziałeś, to 1 kwietnia będzie 4 marca ze względu na restrukturyzację (nie wiem, czy to dobrze powiedziane), która została dokonana, co myślisz ?
tachomi

Miesiąc przed 1 kwietnia to 1 marca, a miesiąc przed 1 marca to 1 lutego. To nie są problemy. Problem polega na tym, że na miesiąc przed 31 maja przypada 1 maja, ponieważ 31 kwietnia nie istnieje. Powinieneś sprawdzić numer dnia daty sprzed miesiąca, a nie dzień bieżącej daty.
rici

2
Doh! Fakt, że „miesiąc temu” w niektóre określone dni w dowolnym miesiącu może skutkować w tym samym miesiącu, nie jest niczym, czego można oczekiwać od datewdrożenia; w mojej książce jest semantycznie sprzeczna z intuicją. - Dzięki za zwrócenie na to uwagi, dobrze wiedzieć.
Janis

2

Zamiast polegać na nazwach plików podczas usuwania plików kopii zapasowych, bezpieczniej byłoby polegać na ich metadanych dotyczących czasu.

Na przykład możesz usunąć wszystkie pliki starsze niż 30 dni za pomocą tego polecenia:

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

Jako darmowy bonus, codzienne uruchamianie pozwoli ci zachować ciągłe tworzenie kopii zapasowych, co pozwoli na lepsze zarządzanie miejscem na dysku.

Aby zachować 1 lub 15 plik, możesz albo przechowywać je w innym katalogu, albo zaktualizować polecenie find opcją -not -name.


0

Możesz spróbować zobaczyć, jak działa data, wykonując następujące czynności:

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

Myślę więc, że na podstawie aktualnego miesiąca z poprzedniego miesiąca (nie aktualnego, jeśli to marzec), zmniejsza liczbę dni od ostatniego miesiąca od bieżącego miesiąca.

Możesz wypróbować następującą składnię, aby usunąć pliki starsze niż kilka dni (w przykładzie poniżej 31 dni). Jedna linia do rozwiązania problemu (jest to proste podejście).

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

Aby uzyskać bardziej szczegółowe podejście, możesz również zrobić coś takiego: 1. Znajdowanie liczby dni dla bieżącego miesiąca:

cal $(date +%m) $(date +%y) | egrep -v "$(date +%y)|Su" | xargs | awk '{print $NF}'
  1. Znajdowanie liczby dni w ostatnim miesiącu:

    echo "$ (cal $ (data +% m) $ (data +% y) | egrep -v" $ (data +% y) | Su "| xargs | awk '{print $ NF}') -" $ ( cal $ (data -d "+1 miesiąc temu" +% m) $ (data +% y) | egrep -v "$ (data +% y) | Su" | xargs | awk '{print $ NF}') | pne

  2. Teraz widzimy różnicę między tymi dwoma miesiącami:

    echo "$ (cal $ (data +% m) $ (data +% y) | egrep -v" $ (data +% y) | Su "| xargs | awk '{print $ NF}') -" $ ( cal $ (data -d "+1 miesiąc temu" +% m) $ (data +% y) | egrep -v "$ (data +% y) | Su" | xargs | awk '{print $ NF}') | pne

Teraz możemy przypisać niektóre zmienne do tych 3 kroków. Krok 1 Nazwa zmiennej: FCM Krok 2 Nazwa zmiennej: FLM Krok 3 Nazwa zmiennej: 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)

Sprawdź, czy $ DCL wynosi 0 (zero) i usuń na podstawie różnicy między $ FCM i $ 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

Możesz także dodać zmienną do „/ path / to / folde / with / arhives /”.

Wniosek: jeśli chcesz usunąć pliki starsze niż miesiąc (dokładnie), musisz dostosować dokładną liczbę dni, jeśli używasz polecenia „data” i „+1 miesiąc temu”.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.