1

I know this is a common question, but I do not understand how the solutions provided work. Everyone advises to change the date to seconds from the epoch and then divide by (24 * 3600) to get the difference in days. Or use

if [ $first_date -gt $second_date ]

However, what I don't understand is why no one notices the glaring mistake of using seconds from epoch in that they would differ even within a day. Or if you consider 5:30 pm of a specific day and 9:00 am of the next day, the difference between the seconds won't lead to a gap of 24 hours, and thus, they would be erroneously considered to be the same day.

My usage scenario is this: I need to purge logs that are older than a given number of days. Thus, my expiration_date, which I am forming after taking the user input of the number of days is:

expiration_date=$(date -d "-$1 day" + %s)

My file modification dates I am getting by using stat command as follows:

file_date=$( stat -c %Y $entry )

I need to compare these two dates and purge them if the file modification dates are "less than" the expiration date. Please help me in this regard.

EDIT

I am really confused as to the use of the mtime argument of the find command. Let's consider that we have the following files:

Nov15_1
Nov15_2
Nov17_1
Nov17_2
Nov18_1
Nov18_2
Nov19_1
Nov19_2
  • If I now run the find command using 0 as the mtime argument on Nov 19, it's giving me all the files except the first four.
    $ find /dir/ -type f -mtime 0 -name "Nov*"
    Nov18_1
    Nov18_2
    Nov19_1
    Nov19_2
    
  • And if I run it using +0, it's giving me only the first four files.
    $ find /dir/ -type f -mtime +0 -name "Nov*"
    Nov15_1
    Nov15_2
    Nov17_1
    Nov17_2
    

If we express this using variables, saying that we want to purge logs from the nth day of the month and further back, and we run the command on the (n+1)th day using mtime as +0, which should translate to "1 day back and further", it's actually taking the files from the (n-1)th day and back, i.e. from "2 days back and further". Does this mean that there is no way to get just the files from 1 day back and further somehow? The argument of 0 is mixing it with today's files as well.

EDIT

So I incorporated the -daystart option as pointed out by @AdminBee, and results are as per my expectations. Now if I run the command on the (n+1)th day trying to remove the logs of the nth day and earlier, the command would be

find /dir/ -type f -daystart -mtime +0 -name "Nov*"

Irrespective of whether the file modification timestamp is within the 24-hour period moving back from now, it will now consider the files of the previous day as being behind by 1 day, and will also list all other files previous to them.

AdminBee
  • 22,803
  • 1
    You might be happy with the mtime option of find – Panki Nov 18 '19 at 10:20
  • 1
    https://unix.stackexchange.com/search?q=ddiff points to several possible duplicates – Stéphane Chazelas Nov 18 '19 at 10:28
  • 1
    "Or if you consider .... erroneously considered to be the same day" wouldn't they be considered different fractions of different days? – muru Nov 18 '19 at 10:29
  • "after taking the user input": how do you formulate that? Could not a user make a glaring mistake easily? –  Nov 18 '19 at 16:38
  • "...nth day of the month..." I think you like to confuse yourself. –  Nov 19 '19 at 07:24
  • @rastafile, there is no option to give superscript here, otherwise I would have written pth day of month. But I thought that would be more confusing. Which is why I clearly wrote nth day of month, if it's 19, it's the 19th day of the month. Simple. – supriyo_basak Nov 19 '19 at 07:25
  • It boils down to what you mean with e.g. "delete testerday's files": is that calender day minus 1, or a difference gretaer than 24h? If there is any glaring mistake around, it is this conectpual knot. Your new edit lacks the dates - compare it to my "here.sh" example, which is one-and-a-half days old. In words it is not easy to describe. It is ~43 hours ago -- "more than a day old". –  Nov 19 '19 at 07:35
  • Use touch -d and ls -l to make an example for a new Q! –  Nov 19 '19 at 07:38
  • I think i't kind of philosophical whether a file being four hours old (while crossing the calendar's day boundary) can be considered to be one day old ;-) – U. Windl Aug 17 '23 at 07:15

2 Answers2

1

You would probably need to provide more details on the actual use case. I assume you have a cleanup script running daily and want to remove all files older that, say, 5 days (so from 6 days ago or earlier).

Under these circumstances, you could combine the conditional file search and remove operation into one command by using find (here assuming GNU find or compatible), as in

find /start/of/logfile/dir/structure ! -type d -daystart -mtime +5 -delete

which if run at 2019-11-16 22:54:12 local time, would delete non-directory files whose last modification time is before 2019-11-11 00:00:00 (so files from the 10th and older).

Note that the -daystart option to this find command should achieve your desired behaviour. If you need restrict the operation to specific filename parts, you will have to add -name <pattern> (cf. the documentation to GNU find).

Also note that depending on the version of find installed on your machine, the -delete operation may not be available, so you may have to use -exec rm {} \; instead.

AdminBee
  • 22,803
  • So, from your example, I have the feeling that if I have to purge logs from n number of days back and further, I will have to give the argument to mtime as +(n-1). Please correct me if I'm wrong. – supriyo_basak Nov 18 '19 at 11:13
  • Yes, I believe you are right, and my own tests support that. I would still recommend to err on the safe side and test "non-destructively" if the filter rules do exactly what you intend. – AdminBee Nov 18 '19 at 11:52
  • @Stéphane Chazelas good point updating the filter rules, thanks you! – AdminBee Nov 18 '19 at 11:53
  • Please take a look at the edit of my question which I posted after testing the command. – supriyo_basak Nov 19 '19 at 07:00
  • I may be mistaken, but could it be that you forgot the -daystart option in the tests you mentioned? If it is omitted, the -mtime argument will amount to "n24h from the current time", not "n24h from last midnight". Also, not that the + or - sign to the -mtime argument is relevant: If no sign is supplied, it means "last modified between n24h and (n+1)24h ago". If you add a + or -, this is considered start or end of a range of modification times. – AdminBee Nov 19 '19 at 07:48
  • Thanks a lot, @AdminBee, for pointing out the -daystart option once again. I had indeed glossed over it. I performed some more tests and it's now working fine, just the way I expected. – supriyo_basak Nov 19 '19 at 10:34
  • 1
    @abhishek glad to hear it! – AdminBee Nov 19 '19 at 10:37
0

man find, -atime:

...so to match -atime +1, a file has to have been accessed at least two days ago.

Option -daystart changes the interpretation:

-daystart
 Measure times (for -amin, -atime, -cmin, -ctime, -mmin, and  -mtime)
 from the beginning of today rather than from 24 hours ago.  

touch -d '2019-11-19 0800' thismorning lets you easily create testfiles:

]# find -name '*n*g*' -daystart -mtime 0 -ls 
      Nov 19 08:00 ./thismorning
]# find -name '*n*g*' -daystart -mtime 1 -ls 
      Nov 18 22:30 ./lastnight
      Nov 18 08:30 ./lastmorning
]# find -name '*n*g*'  -mtime 0 -ls 
      Nov 18 22:30 ./lastnight
      Nov 19 08:00 ./thismorning
]# find -name '*n*g*'  -mtime 1 -ls 
      Nov 17 22:00 ./lastlastnight
      Nov 18 08:30 ./lastmorning

(I snipped away -ls output fields -- only left the dates and filenames)

]# find -name '*n*g*'; date         
./lastnight
./thismorning
./lastlastnight
./lastmorning
Tue Nov 19 10:34:33 UTC 2019
]# find -name '*n*g*' -daystart -mtime 2 -ls 
   Nov 17 22:00 ./lastlastnight
]# 

...because you mix up calender days and 24h-periods in your OP. Sometimes we want this, sometimes that.

Why seconds since epoch?

If you want to know how long something lasted, i.e. the difference of two dates, our calender has these irregularities (the months). So either use your knuckles, know about emperors Julius and Augustus, or use brute force via seconds.

From 30.7. to 1.9. is three days longer than 30.1. to 1.3., and it even depends on leap years.

today, 5:30 pm and tomorrow 6:00 am are

  • different days (calendar wise)
  • only half a day apart (day=duration of 24x60x60 seconds)

From your expiration_date I deduct you want to count the 24h periods passed. That means at 1:00am most of "yesterday" is unaffected.

I tested and correted the date command

]# date -d "-1 day" +%s
1574003538
]# date -d "-0 day" +%s
1574089945

The difference is 86407 i.e 24x60x60.

(And if somebodey asks me: "What were you doing at date -d @1574089945?" I can say: "I was editing a command for seven seconds")


]# find . -atime 1
./here.sh
]# find . -atime +0 -atime -2
./here.sh
]# ls -l here.sh 
-rw-r--r-- 1 root root 154 Nov 16 21:37 here.sh

Now is Nov 18 16:43. So there is one full 24h period between.

  • From your example, I can understand that as the file had been accessed a little more than 24 hours ago, it came up in +0. So, please explain this to me once and for all: does find consider the hours gap for considering whether a file is more than a day old? Or does it consider calendar days? And what would I do if my use case was for calendar days (which it is), not the difference in hours? – supriyo_basak Nov 19 '19 at 07:44
  • @abhishek I added the -daystart definition of man find. I did not test or meditate on that, but this must be it. Still: think about how to translate that into a user prompt / natural language. Do you throw away yesterday's paper at 00:20 am? (you can, but it needs clear definitions). –  Nov 19 '19 at 08:03