Como funciona a opção "1 mês atrás" no comando date?

22

Não tenho certeza se essa data está dentro do dia atual ou se leva apenas 30 ou 31 dias.

por exemplo

Se a data atual é March 28th1 mês atrás, deve ser February 28th, mas o que acontece quando é March 30th?

Cenário

Quero fazer backup de alguns arquivos todos os dias, o script salvará esses arquivos dentro da data atual com o $(date +%Y%m%d)formato, como 20150603_bckp.tar.gz, por exemplo, quando chegar o próximo mês, remova todos os arquivos dentro de 1 mês atrás, exceto os arquivos do 1º e do 15º, então é isso minha condição:

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

Mas eu quero saber, o que acontecerá quando a data for 30, 31 ou mesmo o exemplo de fevereiro passado? Vai manter esses arquivos? ou remover arquivos do 1º dia?

Quando é 31, a depuração será executada. Portanto, se o mês passado tiver apenas 30 dias, isso removerá o 1º arquivo do dia?

Espero ter sugerido.

tachomi
fonte
1
Você não saberia que estou aqui no dia 30 de março por esse motivo exato
user7203 30/03

Respostas:

24

- 1 monthsubtrairá um do número do mês e, se a data resultante não for válida ( February 30por exemplo), ajuste-a para que seja válida. Assim December 31 - 1 monthé December 1, não é um dia em novembro e March 31 - 1 monthé March 3(a menos que seja executado em um ano bissexto).

Aqui está uma citação da página de informações do Gnu date(que é a dateversão que implementa essa sintaxe), que inclui uma boa sugestão para tornar a aritmética mais robusta:

A distorção nas unidades pode causar problemas com itens relativos. Por exemplo, 2003-07-31 -1 monthpode ser avaliado para 01/07/2003, porque 31-06-2003 é uma data inválida. Para determinar o mês anterior com mais confiabilidade, você pode solicitar o mês anterior ao dia 15 do mês atual. Por exemplo:

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

Outro aviso, também citado na página de informações:

Além disso, tenha cuidado ao manipular datas em torno das alterações do relógio, como saltos no horário de verão. Em alguns casos, eles adicionaram ou subtraíram até 24 horas do relógio; portanto, é aconselhável adotar o tempo universal definindo a TZvariável de ambiente UTC0 antes de iniciar os cálculos de calendário.

rici
fonte
Eu tenho uma dúvida aqui, especificamente na situação de fevereiro ... Quando são 29, 30 ou 31 de março, pode levar o seguinte número do mês passado se o atual não existir, portanto, nessas três situações, pode demorar 1 de março não? Porque se 29, 30, 31 de março e depois 1, 2 e 3 de março, como você disse, então 1º de abril será 4 de março devido à reestruturação (não sei se é bem dito) feita, o que você acha ?
precisa saber é
Um mês antes de 1º de abril é 1º de março e um mês antes de 1º de março é 1º de fevereiro. Estes não são problemas. O problema é que um mês antes de 31 de maio é 1º de maio, porque 31 de abril não existe. Você deve verificar o número do dia da data de um mês atrás, não o dia da data atual.
rici
2
Doh! O fato de "um mês atrás" de alguns dias específicos em qualquer mês poder resultar no mesmo mês não é nada que eu esperaria de uma dateimplementação; no meu livro, é semanticamente contra-intuitivo. - Obrigado por apontar isso, é bom saber.
Janis
2

Em vez de confiar nos nomes de arquivos para remover seus arquivos de backup, você estaria mais seguro contando com os metadados de tempo deles.

Por exemplo, você pode excluir todos os arquivos com mais de 30 dias com este comando:

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

Como um bônus grátis, a execução diária todos os dias permitirá que você mantenha seus arquivos de backup em um mês consecutivo, permitindo um melhor gerenciamento do espaço em disco.

Para manter os arquivos 1 ou 15, você pode armazená-los em outro diretório, ou atualizar o comando find com a opção -not -name.

Bertrand Lupart
fonte
0

Você pode tentar ver como a data funciona da seguinte maneira:

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

Então, acho que, com base no atual mês passado (não atual, se é março), diminui o número de dias desde o último mês a partir do mês atual.

Você pode tentar a seguinte sintaxe para excluir arquivos com mais de um número de dias (no exemplo abaixo de 31 dias). Uma linha para resolver o problema (isto é para uma abordagem simples).

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

Para uma abordagem mais detalhada, você também pode fazer algo assim: 1. Encontrar o número de dias para o mês atual:

cal $(date +%m) $(date +%y) | egrep -v "$(date +%y)|Su" | xargs | awk '{print $NF}'
  1. Localizando o número de dias do último mês:

    echo "$ (cal $ (data +% m) $ (data +% y) | egrep -v" $ (data +% y) | Su "| xargs | awk '{print $ NF}') -" $ ( cal $ (data -d "há um mês atrás" +% m) $ (data +% y) | egrep -v "$ (data +% y) | Su" | xargs | awk '{print $ NF}') | bc

  2. Então agora encontramos a diferença entre esses dois meses:

    echo "$ (cal $ (data +% m) $ (data +% y) | egrep -v" $ (data +% y) | Su "| xargs | awk '{print $ NF}') -" $ ( cal $ (data -d "há um mês atrás" +% m) $ (data +% y) | egrep -v "$ (data +% y) | Su" | xargs | awk '{print $ NF}') | bc

Agora vamos atribuir algumas variáveis ​​a essas 3 etapas. Etapa 1 Nome da variável: FCM Etapa 2 Nome da variável: FLM Etapa 3 Variável 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)

Verifique se $ DCL é igual a 0 (zero) e exclua com base na diferença entre $ FCM e $ 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

Você também pode adicionar uma variável a "/ path / to / folde / with / arhives /".

Conclusão: Se você deseja excluir arquivos com mais de um mês (exatamente), precisará ajustar o número exato de dias, se estiver usando o comando "date" e "+1 month ago".

Mihai M
fonte