¿Cómo funciona la opción "Hace 1 mes" en el comando de fecha?

22

No estoy seguro de si esto tiene la fecha pasada dentro del día actual o si solo lleva 30 o 31 días.

p.ej

Si la fecha actual es March 28th, debe ser hace 1 mes February 28th, pero ¿qué sucede cuando es March 30th?

Guión

Quiero hacer una copia de seguridad de algunos archivos todos los días, la secuencia de comandos guardará estos archivos dentro de la fecha actual con el $(date +%Y%m%d)formato, por ejemplo 20150603_bckp.tar.gz, cuando llegue el próximo mes, elimine todos esos archivos dentro de 1 mes, excepto los archivos 1 y 15, así que esto es Mi Condición:

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

Pero quiero saber, ¿qué sucederá cuando la fecha sea el 30, 31 o incluso el último ejemplo de febrero? ¿Mantendrá esos archivos? o eliminar los archivos del primer día?

Cuando sea el 31, la depuración se ejecutará, por lo que si el último mes solo tuvo 30 días, ¿esto eliminará el primer día del archivo?

Espero haberlo insinuado.

tachomi
fuente
1
¿No
sabrías

Respuestas:

24

- 1 monthrestará uno del número del mes y luego, si la fecha resultante no es válida ( February 30por ejemplo), ajústela para que sea válida. Así December 31 - 1 monthes December 1, no es un día de noviembre, y March 31 - 1 monthes March 3(a menos que se ejecute en un año bisiesto).

Aquí hay una cita de la página de información para Gnu date(que es la dateversión que implementa esta sintaxis), que incluye una buena sugerencia para hacer que la aritmética sea más robusta:

La pelusa en las unidades puede causar problemas con los elementos relativos. Por ejemplo, 2003-07-31 -1 monthpodría evaluar a 01/07/2003, porque 2003-06-31 es una fecha no válida. Para determinar el mes anterior de manera más confiable, puede solicitar el mes anterior al 15 del mes actual. Por ejemplo:

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

Otra advertencia, también citada en la página de información:

Además, tenga cuidado al manipular las fechas alrededor de los cambios del reloj, como los saltos de horario de verano. En algunos casos, estos han agregado o restado hasta 24 horas del reloj, por lo que a menudo es aconsejable adoptar la hora universal configurando la TZvariable de entorno UTC0 antes de embarcarse en los cálculos de calendario.

rici
fuente
Tengo una duda aquí, específicamente en la situación de febrero ... Cuando sea el 29, 30 o 31 de marzo, podría tomar el siguiente número del mes pasado si el actual no existe, por lo que en estas tres situaciones podría tomar 1 de marzo no? Porque si el 29, 30, 31 de marzo y luego el 1, 2 y 3 de marzo como dijiste, el 1 de abril será el 4 de marzo debido a la reestructuración (no sé si está bien dicho) que se hizo, ¿qué crees? ?
tachomi
Un mes antes del 1 de abril es el 1 de marzo y un mes antes del 1 de marzo es el 1 de febrero. Estos no son problemas. El problema es que un mes antes del 31 de mayo es el 1 de mayo porque el 31 de abril no existe. Debe verificar el número de día de la fecha de hace un mes, no el día de la fecha actual.
rici
2
Doh! El hecho de que "hace un mes" de algunos días específicos en cualquier mes puede resultar en el mismo mes no es nada de lo que esperaría de una dateimplementación; en mi libro es semánticamente contra-intuitivo. - Gracias por señalar eso, es bueno saberlo.
Janis
2

En lugar de confiar en los nombres de archivo para purgar sus archivos de copia de seguridad, estaría más seguro confiando en sus metadatos de tiempo.

Por ejemplo, puede eliminar todos los archivos de más de 30 días con este comando:

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

Como beneficio adicional, ejecutar esto todos los días le permitirá mantener sus archivos de respaldo en un mes continuo, lo que permite una mejor administración del espacio en disco.

Para guardar los archivos 1º o 15º, puede almacenarlos en otro directorio, actualizar el comando find con la opción -not -name.

Bertrand Lupart
fuente
0

Podría intentar ver cómo funciona la fecha de la siguiente manera:

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

Entonces, creo que según el mes pasado (no es el mes de marzo), disminuye el número de días desde el último mes desde el mes actual.

Puede probar la siguiente sintaxis para eliminar archivos anteriores a un número de días (en el ejemplo, por debajo de 31 días). Una línea para resolver el problema (esto es para un enfoque simple).

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

Para un enfoque más detallado, también puede hacer algo como esto: 1. Encontrar el número de días para el mes actual:

cal $(date +%m) $(date +%y) | egrep -v "$(date +%y)|Su" | xargs | awk '{print $NF}'
  1. Encontrar el número de días para el último mes:

    echo "$ (cal $ (fecha +% m) $ (fecha +% y) | egrep -v" $ (fecha +% y) | Su "| xargs | awk '{print $ NF}') -" $ ( cal $ (fecha -d "+1 mes atrás" +% m) $ (fecha +% y) | egrep -v "$ (fecha +% y) | Su" | xargs | awk '{print $ NF}') El | antes de Cristo

  2. Entonces ahora encontramos la diferencia entre esos dos meses:

    echo "$ (cal $ (fecha +% m) $ (fecha +% y) | egrep -v" $ (fecha +% y) | Su "| xargs | awk '{print $ NF}') -" $ ( cal $ (fecha -d "+1 mes atrás" +% m) $ (fecha +% y) | egrep -v "$ (fecha +% y) | Su" | xargs | awk '{print $ NF}') El | antes de Cristo

Ahora asignemos algunas variables a estos 3 pasos. Paso 1 Nombre de la variable: FCM Paso 2 Nombre de la variable: FLM Paso 3 Nombre de la variable: 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 si $ DCL es igual a 0 (cero) y elimine en función de la diferencia entre $ FCM y $ 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

También puede agregar una variable a "/ ruta / a / folde / with / arhives /".

Conclusión: si desea eliminar archivos anteriores a un mes (exactamente), debe ajustar el número exacto de días, si está utilizando el comando "fecha" y "hace +1 mes".

Mihai M
fuente