1

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'
2
  • 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 '19 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 '19 at 16:31
3

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 /dev/null {} +
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. I've added /dev/null as a "file" for grep to search from along with the filenames from find, if any. That way, if there is only one matching file, grep is "forced" to report the matching filename (as /dev/null will never match, it won't be reported).

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

3
  • 5
    ... or with GNU find, you could use date strings directly I think e.g. -newermt '21 Feb' ! -newermt '22 Feb' – steeldriver Feb 27 '19 at 19:01
  • I recommend grep -H, in case there's only one matching file. Or, more portably, add /dev/null to the grep command to ensure there's always at least two. – Toby Speight Dec 11 '19 at 14:01
  • Thanks, Toby! I've incorporated the /dev/null suggestion as a more-general solution. Feel free to edit in such excellent suggestions directly next time! – Jeff Schaller Dec 11 '19 at 14:06
1

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.

3
  • consider directly calling -exec grep so that you don't break when filenames contain special characters (spaces, newlines) – Jeff Schaller Feb 27 '19 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 '19 at 19:58
  • Just a warning that most filesystems don't store a creation date - -ctime works on the last inode changed time, which will be updated e.g. when permission bits are changed. – Toby Speight Dec 11 '19 at 13:59
0

Refer to the below screenshot,

enter image description here

We need to list a file that contains a particular string and which is created on a particular date. We can execute the below command for this,

  • sudo find . -type f -newermt 2020-10-06 -exec grep -l "test" {} \;

The above command will list the files created on Oct 6 and which contain the string 'test'. Refer to the below screenshot,

enter image description here

In the first screenshot, you can see 3 files. Two of them (test.scala and text2.txt) contain a string 'test' but their creation date is different. And in the second screenshot, you can see that we listed the file that contains the string 'test' and which is created on Oct 6.

1
  • Welcome to the site, and thank you for your contribution. Please note posting screenshots of console output is discouraged as they are often difficult to read. Instead, copy-and-paste the content as text, using proper formatting. – AdminBee Oct 6 '20 at 15:20
-1

This will work:

$ grep -e JMS111 *20190221*.txt
1
  • Unfortunately, this answer assumes that the file's date is encoded in its file name, which the question does not specify. – Jeff Schaller Dec 11 '19 at 14:07

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.