0

I am having trouble with the Linux find and grep commands. Basically I need to CD to a directory, recursive find all example.txt files modified after a particular date and then execute grep on those files. The command below is working (somewhat) but it gives multiple results of same file and I am not sure how stable it is.

find ./ -name "example.xml" -newermt "2018-01-01" -exec grep -r "videoplayer.1" /. \;
1
  • 1
    Your missing {} at the end of grep! Perhaps this would help: find ./ -name "example.xml" -newermt "2018-01-01" -exec grep -r "videoplayer.1" {} \; Commented Jan 12, 2018 at 17:33

2 Answers 2

2

I would think the correct form of that command is:

find ./ -name "example.xml" -newermt "2018-01-01" -exec grep -r "videoplayer.1" {} \;

Missing the {} part in the find command. Your find results aren't being passed to grep.

7
  • Thanks, George. I think your solution is working but id does not show the path of the file, I've modified it a bit - find ./ -name "example.xml" -newermt "2017-01-08" -exec grep "videoplayer.1" {} ./ \; Do you think that it is reliable? Commented Jan 12, 2018 at 17:41
  • Remove the \; and use + and see if it helps Commented Jan 12, 2018 at 17:45
  • 1
    With \; you are passing only a single file at a time to grep, so it won't print the filename by default - you will need to add the -H option if you want it to add the name. Or add a -print to the find command. Commented Jan 12, 2018 at 18:48
  • Would + not be ok too, and the -print prints all file names Commented Jan 12, 2018 at 19:28
  • 1
    @VitaliyTerziev as you wish my lord, :)! Commented Jan 13, 2018 at 13:04
1
find ./ -name "example.xml" -newermt "2018-01-01" -exec grep -r "videoplayer.1" /. \;

This would find, starting at the current directory ./, files with the -name example.xml that are newer (in modification time) than 2018-01-01 and for each of them, execute the command grep -r "videoplayer.1" /..

But we see that the grep command does not take the file name found by find into account, but instead the command is always constant. Furthermore, it starts a recursive (-r) search from the root of the filesystem (/.). Now, that may be a typo (./ vs. /.), but the meaning changes completely.

Even with grep -r ... ./, the search would be recursive starting from the current directory, and with -exec, that's the directory where find was started.

With find -exec, you need to use the {} placeholder to tell find where to insert the filename currently being processed. So

find ./ -name "example.xml" -newermt "2018-01-01" -exec grep  "videoplayer.1" {} \;

To run grep videoplayer.1 filename on all files named example.xml that are newer than January 1st 2018.

Actually, you could do replace the \; that terminates the -exec command with a + to have find pass multiple files to one invocation of grep. That would make the whole job faster, since less processes need to be started:

find ./ -name "example.xml" -newermt "2018-01-01" -exec grep  "videoplayer.1" {} \+

Also, if you want to make sure grep lists the name of the file it's processing, you can use the -H flag (in at least GNU and BSD grep):

  -H, --with-filename       

Print the file name for each match. This is the default when there is more than one file to search.

(An alternative to -H would be to add something like /dev/null to the list of files given to grep)

3
  • Thanks for the detailed explanation, this is the final version of the command which I am planning to use - find ./ -name "example.xml" -newermt "2018-01-01" -exec grep "videoplayer.1" {} ./ \; Basically the same as the suggested above but with extra "./" so I can see the path and file. Commented Jan 13, 2018 at 12:28
  • @VitaliyTerziev, yeah, GNU and BSD grep have the -H option, which tells it to print the file name in any case. It's what happens by default if multiple files are listed. Also, I forgot to mention find -exec ... {} +, which would be better. Edited notes on both.
    – ilkkachu
    Commented Jan 13, 2018 at 12:36
  • Thanks a lot for the details and examples, I have final version of the command now. :) find ./ -name "example.xml" -newermt "2018-01-01" -exec grep -H "videoplayer.1" {} \+ Commented Jan 13, 2018 at 13:00

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .