Recursively find all files newer than a given time [closed] - linux

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.
Closed 1 year ago.
The community reviewed whether to reopen this question 10 months ago and left it closed:
Original close reason(s) were not resolved
Improve this question
Given a time_t:
⚡ date -ur 1312603983
Sat 6 Aug 2011 04:13:03 UTC
I'm looking for a bash one-liner that lists all files newer. The comparison should take the timezone into account.
Something like
find . --newer 1312603983
But with a time_t instead of a file.

You can find every file what is created/modified in the last day, use this example:
find /directory -newermt $(date +%Y-%m-%d -d '1 day ago') -type f -print
for finding everything in the last week, use '1 week ago' or '7 day ago'
anything you want

Maybe someone can use it. Find all files which were modified within a certain time frame recursively, just run:
find . -type f -newermt "2013-06-01" \! -newermt "2013-06-20"

This is a bit circuitous because touch doesn't take a raw time_t value, but it should do the job pretty safely in a script. (The -r option to date is present in MacOS X; I've not double-checked GNU.) The 'time' variable could be avoided by writing the command substitution directly in the touch command line.
time=$(date -r 1312603983 '+%Y%m%d%H%M.%S')
marker=/tmp/marker.$$
trap "rm -f $marker; exit 1" 0 1 2 3 13 15
touch -t $time $marker
find . -type f -newer $marker
rm -f $marker
trap 0

Assuming a modern release, find -newermt is powerful:
find -newermt '10 minutes ago' ## other units work too, see `Date input formats`
or, if you want to specify a time_t (seconds since epoch):
find -newermt #1568670245
For reference, -newermt is not directly listed in the man page for find. Instead, it is shown as -newerXY, where XY are placeholders for mt. Other replacements are legal, but not applicable for this solution.
From man find -newerXY:
Time specifications are interpreted as for the argument to the -d option of GNU date.
So the following are equivalent to the initial example:
find -newermt "$(date '+%Y-%m-%d %H:%M:%S' -d '10 minutes ago')" ## long form using 'date'
find -newermt "#$(date +%s -d '10 minutes ago')" ## short form using 'date' -- notice '#'
The date -d (and find -newermt) arguments are quite flexible, but the documentation is obscure. Here's one source that seems to be on point: Date input formats

Given a unix timestamp (seconds since epoch) of 1494500000, do:
find . -type f -newermt "$(date '+%Y-%m-%d %H:%M:%S' -d #1494500000)"
To grep those files for "foo":
find . -type f -newermt "$(date '+%Y-%m-%d %H:%M:%S' -d #1494500000)" -exec grep -H 'foo' '{}' \;

You can also do this without a marker file.
The %s format to date is seconds since the epoch. find's -mmin flag takes an argument in minutes, so divide the difference in seconds by 60. And the "-" in front of age means find files whose last modification is less than age.
time=1312603983
now=$(date +'%s')
((age = (now - time) / 60))
find . -type f -mmin -$age
With newer versions of gnu find you can use -newermt, which makes it trivial.

There is PowerShell available on Linux for some time so I recommend to use that since it does not deal just with pure text but handles real objects and so avoids formatting and make the task much easier
ls -recurse | where lastwritetime -gt ((get-date).AddDays(-1))

It's another way. You can recursively find files newer than a given timestamp using touch -d and find /dir -newer commands.
For example, if you need find files newer than '1 June 2018 11:02', you can create a file with this creation date.
touch -d '1 June 2018 11:02' ref_timestamp
Then, you can use the file timestamp as reference in find command.
find /dir -newer ref_timestamp

So there's another way (and it is portable to some extent_
(python <<EOF
import fnmatch
import os
import os.path as path
import time
matches = []
def find(dirname=None, newerThan=3*24*3600, olderThan=None):
for root, dirnames, filenames in os.walk(dirname or '.'):
for filename in fnmatch.filter(filenames, '*'):
filepath = os.path.join(root, filename)
matches.append(path)
ts_now = time.time()
newer = ts_now - path.getmtime(filepath) < newerThan
older = ts_now - path.getmtime(filepath) > newerThan
if newerThan and newer or olderThan and older: print filepath
for dirname in dirnames:
if dirname not in ['.', '..']:
print 'dir:', dirname
find(dirname)
find('.')
EOF
) | xargs -I '{}' echo found file modified within 3 days '{}'

Related

Shell script to find recently modified files [duplicate]

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.
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
Should be to your liking
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.
Another, more humanist way, is to use -newermt option which understands human-readable time units.
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 /<directory> -newermt "-24 hours" -ls
find /<directory> -newermt "1 day ago" -ls
find /<directory> -newermt "yesterday" -ls
You can do that with
find . -mtime 0
From man find:
[The] time since each file was last modified is divided by 24 hours and any remainder is discarded. That means that to
match -mtime 0, a file will have to have a modification in the past which is less than 24 hours ago.
On GNU-compatible systems (i.e. Linux):
find . -mtime 0 -printf '%T+\t%s\t%p\n' 2>/dev/null | sort -r | more
This will list files and directories that have been modified in the last 24 hours (-mtime 0). It will list them with the last modified time in a format that is both sortable and human-readable (%T+), followed by the file size (%s), followed by the full filename (%p), each separated by tabs (\t).
2>/dev/null throws away any stderr output, so that error messages don't muddy the waters; sort -r sorts the results by most recently modified first; and | more lists one page of results at a time.
For others who land here in the future (including myself), add a -name option to find specific file types, for instance: find /var -name "*.php" -mtime -1 -ls
This command worked for me
find . -mtime -1 -print
Find the files...
You can set type f = file
find /directory_path -type f -mtime -1 -exec ls -lh {} \;
👍

How to grep a group of files within a specific time range

I'm trying to write a script used on a buffer box that does full packet capture of network traffic. As it's for a fairly big network we split the captures into 100MB segments. At times of high network traffic oftentimes over a one minute period we will have multiple pcaps which cover that period.
So what I want to do is have a bash script that lets the analyst who is searching for something specify a date and time and how many minutes either side of it they want to search for files. Obviously I can do something like this -
ls -al | grep "Dec 1" | grep 02:00
ls -al | grep "Dec 1" | grep 02:01
and so on, get each result and grep each file individually for the specific keyword I'm looking for, but I'd like to be able to do a wider search for all files created within a time range and then grep each of them for the keyword.
I'm not entirely sure how to do that, any help would be appreciated.
find . -maxdepth 1 -newermt "2013-10-28 00:00:00" ! -newermt "2013-10-29 00:00:00"
What I want is for an analyst to say 1st December at 11:00am with a
keyword of "foo" searching 5 minutes either side. The script should
find all files created between 10:55am and 11:05am and grep them for
the keyword "foo"
This script uses touch -d to create temporary files with time stamps of the start and end of the time range, because older versions of find have the option -newer only, not -newermt, and touch -d conveniently allows using the given time specification (with little modification) with the minutes adjustment. The necessary modifications to the given date are done with sed and consist of moving the day after the month and removing suffixes as st or nd as well as the word at.
read -p'date and time: ' dat
read -p'+/- minutes: ' min
read -p'keyword: ' key
dat=`sed 's/\([0-9]\+\)\(st\|nd\|rd\|th\|\) \([^ ]*\)/\3 \1/; s/at //' <<<$dat`
touch -d"$dat $min min" /tmp/to
touch -d"$dat -$min min" /tmp/from
find . -type f -newer /tmp/from ! -newer /tmp/to | xargs grep "$key"
rm /tmp/from /tmp/to
Check out find with the -cmin or -ctime arguments.
So,
find -iname "*.log" -mtime +30 -mtime -90 -exec grep plasma {} \;
, would find files ending in ".log" which were modified greater than 30 days ago, but less than 90 days, then run said file through grep looking for the word "plasma".
Say you want 20131130 from 0100 to 0130 -
This does that with find:
touch -t 201311300100 dummy1
touch -t 201311300130 dummy2
find /path/to/logs type -f \( -newer dummy1 -a ! -newer dummy2 \) -name '*.log'
the 201311300100 bit is a touch timestring. I posted the most vanilla version I know because of the UNIX tag....

Find files in created between a date range

I use AIX via telnet here at work, and I'd like to know how to find files in a specific folder between a date range. For example: I want to find all files in folder X that were created between 01-Aug-13 and 31-Aug-13.
Observations:
The touch trick (where you create two empty files to use the -newer option) does not work for me, once the user roles that I have on the server does not allow me to create files.
I need to find between specific dates, not days (like: files that were created more than 30 days ago, etc...)
If you use GNU find, since version 4.3.3 you can do:
find -newerct "1 Aug 2013" ! -newerct "1 Sep 2013" -ls
It will accept any date string accepted by GNU date -d.
You can change the c in -newerct to any of a, B, c, or m for looking at atime/birth/ctime/mtime.
Another example - list files modified between 17:30 and 22:00 on Nov 6 2017:
find -newermt "2017-11-06 17:30:00" ! -newermt "2017-11-06 22:00:00" -ls
Full details from man find:
-newerXY reference
Compares the timestamp of the current file with reference. The reference argument is normally the name of a file (and one of its timestamps is used
for the comparison) but it may also be a string describing an absolute time. X and Y are placeholders for other letters, and these letters select
which time belonging to how reference is used for the comparison.
a The access time of the file reference
B The birth time of the file reference
c The inode status change time of reference
m The modification time of the file reference
t reference is interpreted directly as a time
Some combinations are invalid; for example, it is invalid for X to be t. Some combinations are not implemented on all systems; for example B is not
supported on all systems. If an invalid or unsupported combination of XY is specified, a fatal error results. Time specifications are interpreted as
for the argument to the -d option of GNU date. If you try to use the birth time of a reference file, and the birth time cannot be determined, a fatal
error message results. If you specify a test which refers to the birth time of files being examined, this test will fail for any files where the
birth time is unknown.
Try the following command:
find /var/tmp -mtime +2 -a -mtime -8 -ls
This will allow you to find files in /var/tmp folder that are older than 2 days but not older than 8 days.
Some good solutions on here. Wanted to share mine as well as it is short and simple.
I'm using find (GNU findutils) 4.5.11
$ find search/path/ -newermt 20130801 \! -newermt 20130831
You can use the below to find what you need.
Find files older than a specific date/time:
find ~/ -mtime $(echo $(date +%s) - $(date +%s -d"Dec 31, 2009 23:59:59") | bc -l | awk '{print $1 / 86400}' | bc -l)
Or you can find files between two dates. First date more recent, last date, older. You can go down to the second, and you don't have to use mtime. You can use whatever you need.
find . -mtime $(date +%s -d"Aug 10, 2013 23:59:59") -mtime $(date +%s -d"Aug 1, 2013 23:59:59")
Use stat to get the creation time. You can compare the time in the format YYYY-MM-DD HH:MM:SS lexicographically.
This work on Linux with modification time, creation time is not supported. On AIX, the -c option might not be supported, but you should be able to get the information anyway, using grep if nothing else works.
#! /bin/bash
from='2013-08-01 00:00:00.0000000000' # 01-Aug-13
to='2013-08-31 23:59:59.9999999999' # 31-Aug-13
for file in * ; do
modified=$( stat -c%y "$file" )
if [[ $from < $modified && $modified < $to ]] ; then
echo "$file"
fi
done
You can use the following commands to list files between 2 specific dates:
Search on current (.) directory:
find . -type f -newermt "2019-01-01" ! -newermt "2019-05-01"
Search on /var/any/directory/ directory:
find /var/any/directory/ -type f -newermt "2019-01-01" ! -newermt "2019-05-01"
Script oldfiles
I've tried to answer this question in a more complete way, and I ended up creating a complete script with options to help you understand the find command.
The script oldfiles is in this repository
To "create" a new find command you run it with the option -n (dry-run), and it will print to you the correct find command you need to use.
Of course, if you omit the -n it will just run, no need to retype the find command.
Usage:
oldfiles [-v...] ([-h|-V|-n] | {[(-a|-u) | (-m|-t) | -c] (-i | -d | -o| -y | -g) N (-\> | -\< | -\=) [-p "pat"]})
Where the options are classified in the following groups:
Help & Info:
-h, --help : Show this help.
-V, --version : Show version.
-v, --verbose : Turn verbose mode on (cumulative).
-n, --dry-run : Do not run, just explain how to create a "find" command
Time type (access/use, modification time or changed status):
-a or -u : access (use) time
-m or -t : modification time (default)
-c : inode status change
Time range (where N is a positive integer):
-i N : minutes (default, with N equal 1 min)
-d N : days
-o N : months
-y N : years
-g N : N is a DATE (example: "2017-07-06 22:17:15")
Tests:
-p "pat" : optional pattern to match (example: -p "*.c" to find c files) (default -p "*")
-\> : file is newer than given range, ie, time modified after it.
-< : file is older than given range, ie, time is from before it. (default)
-= : file that is exactly N (min, day, month, year) old.
Example:
Find C source files newer than 10 minutes (access time) (with verbosity 3):
oldfiles -a -i 10 -p"*.c" -\> -nvvv
Starting oldfiles script, by beco, version 20170706.202054...
oldfiles -vvv -a -i 10 -p "*.c" -\> -n
Looking for "*.c" files with (a)ccess time newer than 10 minute(s)
find . -name "*.c" -type f -amin -10 -exec ls -ltu --time-style=long-iso {} +
Dry-run
Find H header files older than a month (modification time) (verbosity 2):
oldfiles -m -o 1 -p"*.h" -\< -nvv
Starting oldfiles script, by beco, version 20170706.202054...
oldfiles -vv -m -o 1 -p "*.h" -\< -n
find . -name "*.h" -type f -mtime +30 -exec ls -lt --time-style=long-iso {} +
Dry-run
Find all (*) files within a single day (Dec, 1, 2016; no verbosity, dry-run):
oldfiles -mng "2016-12-01" -\=
find . -name "*" -type f -newermt "2016-11-30 23:59:59" ! -newermt "2016-12-01 23:59:59" -exec ls -lt --time-style=long-iso {} +
Of course, removing the -n the program will run the find command itself and save you the trouble.
I hope this helps everyone finally learn this {a,c,t}{time,min} options.
The LS output:
You will also notice that the ls option ls OPT changes to match the type of time you choose.
Link to clone/download of the oldfiles script:
https://github.com/drbeco/oldfiles
Explanation: Use unix command find with -ctime (creation time) flag.
The find utility recursively descends the directory tree for each path listed, evaluating an expression (composed of the 'primaries' and 'operands') in terms of each file in the tree.
Solution: According to official documentation:
-ctime n[smhdw]
If no units are specified, this primary evaluates to true if the difference
between the time of last change of file status information and the time find
was started, rounded up to the next full 24-hour period, is n 24-hour peri-
ods.
If units are specified, this primary evaluates to true if the difference
between the time of last change of file status information and the time find
was started is exactly n units. Please refer to the -atime primary descrip-
tion for information on supported time units.
Formula:
find <path> -ctime +[number][timeMeasurement] -ctime -[number][timeMeasurment]
Examples:
1.Find everything that were created after 1 week ago and before 2 weeks ago.
find / -ctime +1w -ctime -2w
2.Find all javascript files (.js) in current directory that were created between 1 day ago to 3 days ago.
find . -name "*\.js" -type f -ctime +1d -ctime -3d

Finding files modified within an hour of another file

If i have 3 files called 1.txt,2.txt and 3.txt for example and they were created an hour apart, say 1pm 2pm and 3pm respectively. What I need is a command that finds all files modified within an hour of a specific file.
I'm in the same directory as the files in the terminal and all files are setuid permission
I've been trying:
find . -type f -perm -4000 -newer 2.txt -mmin -60 -print
This should return 3.txt but it doesn't
What would use to file created in the hour before or after 2.txt?
Try this
touch /tmp/temp -t time1
touch /tmp/ntemp -t time2
find . -newer /tmp/temp -a ! -newer /tmp/ntemp -exec ls -l {} \; 2>/dev/null
where
time1 = time of file creation - 1hr
time2 = time of file creation + 1hr
Ex:
time1 = 201210041500
time2 = 201210041700
Here is my logic -
First get time of last access of file in seconds since Epoch in some variable.
time_in_sec=$(stat -c %X 2.txt)
Get the time of last hour ( ie 3600 seconds back )
one_hr_old_time_in_sec=`expr $time_in_sec - 3600`
Convert it into format suitable for find command
newerthan=$(date -d #$one_hr_old_time_in_sec '+%m-%d-%y%n %H:%M:%S')
Convert time of original file in format suitable for find command
olderthan=$(date -d #$time_in_sec '+%m-%d-%y%n%H:%M:%S')
Get the list of files modified between two time periods using find command
find . -newermt "$newerthan" ! -newermt "$olderthan" -print
If it works you can write a small shell script which will take file name as parameter and can try for +3600 also.
Honestly, I haven't tried it. Hope it works !
The previous solution can be simplified since -newermt shall accept the same formats than 'date' including #N for N seconds since epoch.
Also for the 'stat' command it is probably better to use -Y (the time of last modification) instead of -X (the time of last access).
So the command to find the files modified + or - 1 hours of 2.txt is
N=$(stat -c %Y 2.txt)
find . -newermt #$((N-3600)) ! -newermt #$((N+3600)) -print
If you are running this after 4pm, given your example, it makes sense that it wouldn't return 3.txt, as -newer 2.txt -mmin -60 means "modified in the last 60 minutes, and more recently than 2.txt", not "modified less than 60 minutes after 2.txt". I don't think find currently has options to do what you're wanting (at least, the version I have doesn't), but it shouldn't be too hard to script in python or perl.

Finding files by creation time of another file

What I need to do is find files by the creation time of another file. For example if i create a file at 9am and later i wanted to find all the files created 1 hour after it or 1 hour before it. How would i do that?
I've tried experimenting with "-newer" whilst using "find" but I think "xargs" is what i need to be using.
Thanks
I know this is ooooold, but since I was looking for the same thing...
Here's a oneliner version, basically using the same approach as above:
Modified at least one hour after:
find . -newermt "$(date -d "$(stat -c %y reference_file) + 1 hour")"
Modified one hour before or more:
find . -not -newermt "$(date -d "$(stat -c %y reference_file) - 1 hour")"
Modified within the timespan from one hour before to one hour after
find . -newermt "$(date -d "$(stat -c %y reference_file) - 1 hour")" -not -newermt "$(date -d "$(stat -c %y reference_file) + 1 hour")"
Replace reference_file with the file of your choice. You can of course also use othe timespans than 1 hour
How it works
stat -c %y reference_file will return the modification time.
date -d "[...] + 1 hour" will manupulate the date string to one hour later.
find . -newermt "[...]" will find files with modification time (m) newer than given time (t)
All this requires GNU find 4.3.3 or greater (for -newerXY) and GNU date (to support -d and the complex date strings)
After looking at this I found a way to do this, although it is not the nicest solution as it requires integer arithmetic to be done on time.
The idea is to take the seconds since Unix epoch (aka Unix time) from your reference file, do some integer arithmetic on this to get your offset time (one hour before, or after in your example). Then you use find with the -newer parameter.
Example code:
# Get the mtime of your reference file in unix time format,
# assumes 'reference_file' is the name of the file you're using as a benchmark
reference_unix_time=$(ls -l --time-style=+%s reference_file | awk '{ print $6 }')
# Offset 1 hour after reference time
let unix_time_after="$reference_unix_time+60*60"
# Convert to date time with GNU date, for future use with find command
date_time=$(date --date #$unix_time_after '+%Y/%m/%d %H:%M:%S')
# Find files (in current directory or below)which are newer than the reference
# time + 1hour
find . -type f -newermt "$date_time"
For your example of file created upto one hour before the reference file you could use
# Offset 1 hour before reference time
let unix_time_before="$reference_unix_time-60*60"
# Convert to date time with GNU date...
date_time=$(date --date #$unix_time_before '+%Y/%m/%d %H:%M:%S')
# Find files (in current directory or below which were generated
# upto 1 hour before the reference file
find . -type f -not -newermt "$date_time"
Note that all the above is based on the last modification time of files.
The above has been tested with GNU Find (4.5.10), GNU Date (8.15) and GNU Bash (4.2.37).

Resources