How to use ‘find’ to search for files created on a specific date? [closed]
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
9 Answers 9
As pointed out by Max, you can’t, but checking files modified or accessed is not all that hard. I wrote a tutorial about this, as late as today. The essence of which is to use -newerXY and ! -newerXY :
Example: To find all files modified on the 7th of June, 2007:
$ find . -type f -newermt 2007-06-07 ! -newermt 2007-06-08
To find all files accessed on the 29th of september, 2008:
$ find . -type f -newerat 2008-09-29 ! -newerat 2008-09-30
Or, files which had their permission changed on the same day:
$ find . -type f -newerct 2008-09-29 ! -newerct 2008-09-30
If you don’t change permissions on the file, ‘c’ would normally correspond to the creation date, though.
My version of find (GNU 4.2.32) doesn’t seem to support the -newerXY predicates. Is there a particular minimum version needed? Or is it a case of compiling find with a special configure switch?
@yukondude: You’re right. The version of find I have locally — GNU 4.4.0 — has it, while 4.1.20 that I have on Dreamhost doesn’t. The kludge with creating two files should work in either, though.
Note that the -newerxt is available on FreeBSD since 2001 (where it was first provided as a patch in 1998), a few other BSDs and GNU find (since 4.3.3 in 2007), based on HP/UX find, which introduced -newerXY (but where Y == t is not supported).
Note that the exclamation point may need to be escaped ( \! ) if you have Bash history substitution enabled (which is the default). Or you can disable it with set +H .
Use this command to search for files and folders on /home/ add a time period of time according to your needs:
find /home/ -ctime time_period
Examples of time_period:
- More than 30 days ago: -ctime +30
- Less than 30 days ago: -ctime -30
- Exactly 30 days ago: -ctime 30
It’s two steps but I like to do it this way:
First create a file with a particular date/time. In this case, the file is 2008-10-01 at midnight
Now we can find all files that are newer or older than the above file (going by file modified date).
You can also use -anewer for accessed and -cnewer file status changed.
find / -newer /tmp/t find / -not -newer /tmp/t
You could also look at files between certain dates by creating two files with touch
touch -t 0810010000 /tmp/t1 touch -t 0810011000 /tmp/t2
This will find files between the two dates & times
find / -newer /tmp/t1 -and -not -newer /tmp/t2
IMO, right now this should be the accepted solution. I couldn’t get -newermt to run on 2.6.18-348.18.1.el5 kernel, let alone newer kernels.
find ./ -type f -ls |grep '10 Sep'
[root@pbx etc]# find /var/ -type f -ls | grep "Dec 24" 791235 4 -rw-r--r-- 1 root root 29 Dec 24 03:24 /var/lib/prelink/full 798227 288 -rw-r--r-- 1 root root 292323 Dec 24 23:53 /var/log/sa/sar24 797244 320 -rw-r--r-- 1 root root 321300 Dec 24 23:50 /var/log/sa/sa24
mywiki.wooledge.org/ParsingLs — a better approach is probably to print the creation date in machine-readable form, perhaps with stat if you don’t have find -printf .
Regarding «million files» use find ./ -type f -mtime -60 -ls | grep ’10 Sep’ if this date is inside the last 60 days.
You can’t. The -c switch tells you when the permissions were last changed, -a tests the most recent access time, and -m tests the modification time. The filesystem used by most flavors of Linux (ext3) doesn’t support a «creation time» record. Sorry!
In fact, it’s not just the filesystem type — there is no system interface for obtaining such information, even if the filesystem held it. One of the deficiencies of Unix going back to the earliest days, which is why Unix will never take off.
@Max: is right about the creation time.
However, if you want to calculate the elapsed days argument for one of the -atime , -ctime , -mtime parameters, you can use the following expression
ELAPSED_DAYS=$(( ( $(date +%s) - $(date -d '2008-09-24' +%s) ) / 60 / 60 / 24 - 1 ))
Replace «2008-09-24» with whatever date you want and ELAPSED_DAYS will be set to the number of days between then and today. (Update: subtract one from the result to align with find ‘s date rounding.)
So, to find any file modified on September 24th, 2008, the command would be:
find . -type f -mtime $(( ( $(date +%s) - $(date -d '2008-09-24' +%s) ) / 60 / 60 / 24 - 1 ))
This will work if your version of find doesn’t support the -newerXY predicates mentioned in @Arve:’s answer.
Find the latest file by modified date
If I want to find the latest file (mtime) in a (big) directory containing subdirectories, how would I do it? Lots of posts I’ve found suggest some variation of ls -lt | head (amusingly, many suggest ls -ltr | tail which is the same but less efficient) which is fine unless you have subdirectories (I do). Then again, you could
find . -type f -exec ls -lt \ \+ | head
which will definitely do the trick for as many files as can be specified by one command, i.e. if you have a big directory, -exec. \+ will issue separate commands; therefore each group will be sorted by ls within itself but not over the total set; the head will therefore pick up the lastest entry of the first batch. Any answers?
6 Answers 6
You do not need to recur to external commands (as ls ) because find can do all you need through the -printf action:
find /path -printf '%T+ %p\n' | sort -r | head
Yeah, I came up with find . -type f -exec stat —format=%y \ \+ | sort -r | head -n1 but your solution is far cleaner!\>
You can also cull the output of head to include a certain number of lines. I only needed the first line, so I used head -n 1
@qwr wrote «Append | cut -d ‘ ‘ -f2 to get filename only». Thanks! Although better append | cut -d ‘ ‘ -f2 — to avoid problems with filenames that contain spaces.
I had a similar problem today, but I attacked it without find . I needed something short I could run over ssh to return the most recently edited file in my home directory. This is roughly what I came up with:
The -p option to ls adds a trailing slash to directories, the grep -v removes lines ending in a slash (aka, all directories), and the head -1 limits the output to a single file.
This is much less verbose than using find if all you want to return is the file name.
This is on my system faster than printf , though I don’t understand why
find /path -type f -exec stat -c "%y %n" <> + | sort -r | head
EDIT: I guess this post is not ‘not particularly useful’ as I thought it was. This is a really fast solution that just keeps track of the most recently modified file (instead of sorting the entire list of files):
Spread over multiple lines for clarity it looks as follows:
find . -type f -printf '%T@ %p\n' | awk ' BEGIN < mostrecenttime = 0; mostrecentline = "nothing"; > < if ($1 >mostrecenttime) < mostrecenttime = $1; mostrecentline = $0; >> END < print mostrecentline; >' | cut -f2- -d ' '
Not a particularly useful post but since ‘arrange’ was discussing speed, I thought I’d share this.
arrange’s and enzotib’s solutions involve listing all files inside the directory with their mtimes and then sorting. As you know sorting is not necessary to find the maximum. Finding maximum can be done in linear time but sorting takes n log(n) time [I know the difference isn’t much, but still ;)]. I can’t think of a neat way of implementing this. [EDIT: A neat (albeit dirty looking) and fast implementation provided above.]
Next best thing — To find the most recently edited file in a directory, recursively find the most recently edited file in each level 1 subdirectory. Let this file represent the subdirectory. Now sort the level 1 files along with the representatives of the level 1 subdirectories. If the number of number of level 1 files and sub-dirs of each directory is nearly a constant, then this process should scale linearly with total number of files.
This is what I came up with to implement this:
findrecent() < < find "$1" -maxdepth 1 -type f -exec stat -c "%y %n" <>+ | sort -r | head -1 && find "$1" -mindepth 1 -maxdepth 1 -type d -exec findrecent <> \;; > | sort -r | head -1; > findrecent .
I ran this and got a bunch of find: findrecent: No such file or directory errors. Reason: -exec of find runs in a different shell. I tried defining findrecent in .bashrc, .xsessionrc but these didn’t help [I’d appreciate help here]. In the end I resorted to putting
#!/bin/bash < find "$1" -maxdepth 1 -type f -exec stat -c "%y %n" <>+ | sort -r | head -1 && find "$1" -mindepth 1 -maxdepth 1 -type d -exec findrecent <> \;; > | sort -r | head -1;
in a script called findrecent in my PATH and then running it.
I ran this, kept waiting and waiting with no output. Just to be sure I wasn’t dealing with any infinite loops I modified the file to
#!/bin/bash echo "$1" >&2 < find "$1" -maxdepth 1 -type f -exec stat -c "%y %n" <>+ | sort -r | head -1 && find "$1" -mindepth 1 -maxdepth 1 -type d -exec findrecent <> \;; > | sort -r | head -1;
and tried again. It did work — but took 1 minute 35 seconds on my homefolder — arrange’s and enzotib’s solutions took 1.69, 1.95 seconds respectively!
So much for O(n)’s superiority over O(n log (n))! Damn you function call overhead! [Or rather script call overhead]
But this script does scale better than the earlier solutions and I bet it’ll run faster than them on google’s memory bank ;D
Find the files that have been changed in last 24 hours
E.g., a MySQL server is running on my Ubuntu machine. Some data has been changed during the last 24 hours. What (Linux) scripts can find the files that have been changed during the last 24 hours? Please list the file names, file sizes, and modified time.
7 Answers 7
To find all files modified in the last 24 hours (last full day) in a particular specific directory and its sub-directories:
find /directory_path -mtime -1 -ls
The — before 1 is important — it means anything changed one day or less ago. A + before 1 would instead mean anything changed at least one day ago, while having nothing before the 1 would have meant it was changed exacted one day ago, no more, no less.
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.
Another, more humanist way, is to use -newermt option which understands human-readable time units (see man find and search for -newerXY ).
Unlike -mtime option which requires the user to read find documentation to figure our what time units -mtime expects and then having the user to convert its time units into those, which is error-prone and plain user-unfriendly. -mtime was barely acceptable in 1980s, but in the 21st century -mtime has the convenience and safety of stone age tools.
Example uses of -newermt option with the same duration expressed in different human-friendly units:
find / -newermt "-24 hours" -ls find / -newermt "1 day ago" -ls find / -newermt "yesterday" -ls