How can I search for a specific string in files from a specific date?

For example, I have 3 files named

'a1' dated: 20 Feb,
'a2' dated 21 Feb,
'a3' dated 22 Feb.

Now I want to search for a certain string like 'JMS111' in all files where date = '21 Feb'.

I tried below commands but wasn't successful:

ls -lt |grep 'JMS111' -ctime 2019/02/21 
find -name '*.xml' -type f -printf '%Tw:%h/%f\0' | grep 'JMS111'
  • 1
    note that putty is just your interface to some other system (presumably Linux, given the tag); I'll remove the putty tag since your question is more directly about find & grep – Jeff Schaller Feb 27 at 18:47
  • If any of the answers solved your problem, please accept it by clicking the checkmark next to it. Thank you! – Jeff Schaller Mar 17 at 16:31

One way to approach this is to set up timestamp files to bracket the dates you're looking for:

touch -t 201902210000 /tmp/start-time
touch -t 201902212359.59 /tmp/end-time

... and then ask find for files that are newer than the start-time but not newer than the end-time:

find . -type f  -newer /tmp/start-time  ! -newer /tmp/end-time

Putting it all together:

touch -t 201902210000 /tmp/start-time
touch -t 201902212359.59 /tmp/end-time
find . -type f -newer /tmp/start-time  ! -newer /tmp/end-time -name '*.xml' -exec grep JMS111 {} +
rm /tmp/start-time /tmp/end-time

This will look for files in the right timeframe with names ending in .xml and then pass those filenames to the grep, fitting in as many as it can per pass.

Your output will be the filenames and matching lines from those files.

  • 4
    ... or with GNU find, you could use date strings directly I think e.g. -newermt '21 Feb' ! -newermt '22 Feb' – steeldriver Feb 27 at 19:01

You can use

find . -name 'a[123]' -ctime 6 | xargs grep -l 'JMS111'

The -ctime 6 looks for any file that's 6 days old. It actually compares the creation date of the file to the 24 hour period that's between 6*24 hours an 7*24 hours prior to your running the command. If the creation date is in that period, and the filename is 'a1', 'a2', or 'a3', then find prints the path of that file. Since the period specified by -ctime <n> is based on when you ran the find command, you will have to use a different value for <n> if you run find tomorrow, than if you run it today.

Note: If you use -ctime -6, find will print filenames that are 6 or fewer days old, -ctime +6 will print file names that are 6 days or older. Also, some versions of find will allow you to specify units of measurement, e.g 6h, for 6 hours old.

You could instead use -mtime if you want to search on modification time instead of creation time.

Using xargs makes it easy to check if you are getting the correct list of file from find before doing the grep. Also, if you put grep in a -exec primary, find invokes it once for each file it finds, whereas, xargs receives a list of files that it passes to a single invocation of grep, which is less resource intensive.

One disadvantage of -ctime is you have to calculate the number of days since the file was created, but you can figure that out by running

find . -ctime n | xargs ls -l

until you see files with the date you're interested in.

... And, you don't have to remember to delete the bracketing files like you do with -newer.

  • consider directly calling -exec grep so that you don't break when filenames contain special characters (spaces, newlines) – Jeff Schaller Feb 27 at 19:52
  • If files contain spaces (or new-lines) you can change the command to find . -name 'a[123]' -ctime 6 | sed -e "s/.*/'&'" | xargs grep -l 'JMS111' and the filenames will be passed to grep in tact. – hyperbole Feb 27 at 19:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.