1

Im trying to look for the text Elapsed time inside a specific log file names vsim.log. Im not familiar with grep, but after some googling I found that grep -r will allow me to do recursively searches and grep -r "Elapsed time" will do recursive searches for that phrase within all files in my directory. According to this link, I can then do grep -r "Elapsed time" ./vsim* to recursively search through the directories for files starting with vsim and look inside those files for Elapsed time. However, when i tried this i get grep: No match. which i know is not true since I know the files exist there with those keywords. What am i messing up?

4
  • 2
    Why not use the results of find /path/to/search -type f -name "vsim.log" to then search a single or a few files. It will be much faster. Commented Jul 6, 2017 at 17:32
  • @DavidC.Rankin Because I am not very familiar with Linux and am not really aware of the functionalities available as I am still learning. That being said, speed isnt too much of a factor at the moment but I will definitely read into find and probably learn to do it as you mentioned.
    – dorojevets
    Commented Jul 6, 2017 at 17:37
  • I provided an example as an answer. Let me know if you have further questions. Commented Jul 6, 2017 at 17:40
  • The * is not interpreted by grep but by bash. It performs path expansion. This is in turn passed to grep. Likely, nothing expanded in that directory is a directory so there's nothing for grep to recurse into. As one commenter said to an answer, prefer to use . instead of *. Commented Jul 6, 2017 at 18:25

3 Answers 3

2

Continuing from my comment, you can use find to locate the file vsim.log if you do not know its exact location and then use the -execdir option to find to grep the file for the term Elapsed time, e.g.

find path -type f -name "vsim.log" -execdir grep -H 'Elapsed time' '{}' +

That will return the filename along with the matched text which you can simply parse to isolate the filename if desired. You can process all files that match if you anticipate more than one by feeding the results of the find command into a while read -r loop, e.g.

while read -r match; do
    # process "$match" as desired
    echo "Term 'Elapsed time' found in file ${match%:*}"
done < <(find path -type f -name "vsim.log" -execdir grep -H 'Elapsed time' '{}' +)

Where:

  • find is the swiss-army knife for finding files on your system

  • path can be any relative or absolute path to search (e.g. $HOME or /home/dorojevets) to search all files in your home directory

  • the option -type f tells find to only locate files (see man find for link handling)

  • the option -name "foo" tell find to only locate files named foo (wildcards allowed)

  • the -exec and -execdir options allow you to execute the command that follows on each file (represented by '{}')

  • the grep -H 'Elapsed time' '{}' being the command to execute on each filename

  • the + being what tells find it has reached the end of the command (\; used with -exec)

  • finally, the ${match%:*} parameter expansion on the variable $match is used to parse the filename from filename:Elapsed time returned by grep -H (the %:* simply being used to trim everything to the first : from the right of $match)

Give that a try and compare the execution time to a recursive grep of the file tree. What you may be missing in this discussion, is that you use find if you know some part of the filename (or file mod time, or set of permissions, etc) that contains the information you need. It can search millions of files in a file tree vastly quicker than you can recursively grep every single file. If you have no clue what file may contain the needed info -- then use grep and just wait...

4
  • Would this be in a file i execute or do i type the entire thing into the terminal ?
    – dorojevets
    Commented Jul 6, 2017 at 17:47
  • You can just type it into your terminal or include it in a script. Bash is wonderfully flexible. Anything you can do on the command line, you can put in a script and vice-versa... If used in a script, include #!/bin/bash as the first line to tell the interpreter to use bash and not some other shell. I updated the while loop to spit out the full path of the file containing any match of Elapsed time as an example. Commented Jul 6, 2017 at 17:48
  • I also removed tmp which is just the directory name I used to confirm the behavior. It is actually where you tell find to start searching, e.g. find /path/to/search (it will recursively search everything below that). It can be a relative or absolute path. If you run find on the entire root filesystem, include -mount option to prevent searching the /dev, /proc, and /sys system directories that can contain many things that are not files. Commented Jul 6, 2017 at 17:56
  • @dorojevets don't get me wrong, find can be a bit intimidating to make friends with. (especially when you are just starting) But, it is one of those tools that is essential enough to everything you do on a Linux system, that you are well served to go ahead and learn it now. A good general reference is Advanced Bash-Scripting Guide. It too should be your friend. Then use BashGuide - Greg's Wiki to refine your use of bash. Commented Jul 6, 2017 at 18:02
2

Try:

grep -r "Elapsed time" * --include vsim.log

Or this answer Use grep --exclude/--include syntax to not grep through certain files.

1
  • 1
    I would prefer . over * here (no chance of "command line too long", no chance of matching things that look like options to grep, no inconsistent skipping of hidden files on the top level only) Commented Jul 6, 2017 at 18:18
0

The following works just in case if you are using Mac:

To search UUID in *.c files recursively under given folder "/home" use the following:

grep -r "UUID" --include "*.c" /home/

To recursively search UUID in all main.c files in multiple projects under current folder use the following:

grep -r "UUID" --include "main.c" .

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