Why does find -mtime +1 only return files older than 2 days?
I’m struggling to wrap my mind around why the find
interprets file modification times the way it does. Specifically, I don’t understand why the -mtime +1
doesn’t show files less than 48 hours old.
As an example test I created three test files with different modified dates:
[root@foobox findtest]# ls -l
total 0
-rw-r--r-- 1 root root 0 Sep 25 08:44 foo1
-rw-r--r-- 1 root root 0 Sep 24 08:14 foo2
-rw-r--r-- 1 root root 0 Sep 23 08:14 foo3
I then ran find with the -mtime +1
switch and got the following output:
[root@foobox findtest]# find -mtime +1
./foo3
I then ran find with the -mmin +1440
and got the following output:
[root@foobox findtest]# find -mmin +1440
./foo3
./foo2
As per the man page for find, I understand that this is expected behavior:
-mtime n
File’s data was last modified n*24 hours ago. See the comments
for -atime to understand how rounding affects the interpretation
of file modification times.
-atime n
File was last accessed n*24 hours ago. When find figures out
how many 24-hour periods ago the file was last accessed, any
fractional part is ignored, so to match -atime +1, a file has to
have been accessed at least two days ago.
This still doesn’t make sense to me though. So if a file is 1 day, 23 hours, 59 minutes, and 59 seconds old, find -mtime +1
ignores all that and just treats it like it’s 1 day, 0 hours, 0 minutes, and 0 seconds old? In which case, it’s not technically older that 1 day and ignored?
Does… not… compute.
So if a file is 1 day, 23 hours, 59 minutes, and 59 seconds old, find -mtime +1 ignores all that and just treats it like it’s 1 day, 0 hours, 0 minutes, and 0 seconds old?
Yes. Like man find
says, “any fractional part is ignored”. If you divide “1 day, 23 hours, 59 minutes, and 59 seconds” through “24 hours”, you may get 1.9999, but the .9999 part is then stripped and suddenly the file is only 1 day old.
Well, the simple answer is, I guess, that your find implementation is following the POSIX/SuS standard, which says it must behave this way. Quoting from SUSv4/IEEE Std 1003.1, 2013 Edition, “find”:
-mtime n
The primary shall evaluate as true if the file modification time subtracted
from the initialization time, divided by 86400 (with any remainder discarded), is n.
(Elsewhere in that document it explains that n
can actually be +n
, and the meaning of that as “greater than”).
As to why the standard says it shall behave that way—well, I’d guess long in the past a programmer was lazy or not thinking about it, and just wrote the C code (current_time - file_time) / 86400
. C integer arithmetic discards the remainder. Scripts started depending on that behavior, and thus it was standardized.
The spec’d behavior would also be portable to a hypothetical system that only stored a modification date (not time). I don’t know if such a system has existed.
Use -mmin, -amin, etc to get exact results
The argument to -mtime
is interpreted as the number of whole days in the age of the file. -mtime +n
means strictly greater than, -mtime -n
means strictly less than.
Note that with Bash, you can do the more intuitive:
$ find . -mmin +$((60*24))
$ find . -mmin -$((60*24))
to find files older and newer than 24 hours, respectively.
(It’s also easier than typing in a fractional argument to -mtime
for when you want resolution in hours or minutes.)
Fractional 24-hour periods are truncated! That means that “find -mtime +1” says to match files modified two or more days ago.
find . -mtime +0 # find files modified greater than 24 hours ago
find . -mtime 0 # find files modified between now and 1 day ago
# (i.e., in the past 24 hours only)
find . -mtime -1 # find files modified less than 1 day ago (SAME AS -mtime 0)
find . -mtime 1 # find files modified between 24 and 48 hours ago
find . -mtime +1 # find files modified more than 48 hours ago
The following may only work on GNU?
find . -mmin +5 -mmin -10 # find files modified between
# 6 and 9 minutes ago
find / -mmin -10 # modified less than 10 minutes ago
-mtime N
means files whose age A in days satisfies N ≤ A < N+1. In other words, -mtime N
selects files that were last modified between N and N+1 days ago.
-mtime -N
means files whose age A satisfies A < N, i.e. files modified less than N days ago. Less intuitively, -mtime +N
means files whose age A satisfies N+1 ≤ A, i.e. files modified at least N+1 days ago.
For example, -mtime 1
selects files that were modified between 1 and 2 days ago. -mtime +1
selects files that were modified at least 2 days ago. To get files modified at least 1 day ago, use -mtime +0
.
The description “was last modified n*24 hours ago” is only an approximation, and not a very clear one.
If you find these rules hard to remember, use a reference file instead.
touch -d '1 day ago' cutoff
find . -newer cutoff
(The syntax “1 day ago” requires GNU touch
.)
If you want exactly 48-hours-old files, not 2 days, then you should add --daystart
in your find
command. This will help you.
find . type -f -daystart -mtime +1