2

I'd like to use grep to recursively search through a directory, using patterns listed in a file, then store each result in its own file for reference later.

I made an attempt (using this question as a guide) and came up with:

#!/bin/bash

mkdir -p grep_results   # For storing results

echo "Performing grep searches.."
while IFS='' read -r line || [[ -n "$line" ]]; do
    echo "Seaching for $line.."
    grep -r "$line" --exclude-dir=grep_results . > ./grep_results/"$line"_infile.txt
done

echo "Done."

However, when I run it, the console hangs until I hit CTRL-C:

$ bash grep_search.sh search_terms.txt
Performing grep searches..

Where is the issue with this script? Or am I approaching this wrong?

7
  • 3
    on this line grep -r "$line" --exclude-dir=grep_results > ./grep_results/"$line"_infile.txt, I'm unable to see a file name to be looked into. That might be the reason why it hangs until ctrl-c is pressed. – MelBurslan Feb 17 '16 at 18:04
  • Well spotted! Unfortunately it's still not working. I modified my post to include the edited line. – PaleSaint Feb 17 '16 at 18:19
  • 1
    Similar to the previous issue, what is read reading from? Are you manually typing in search strings? Did you mean to run bash grep_search.sh < search_terms.txt? (Also note that bash can read patterns from a file. Check out the -f option.) – muru Feb 17 '16 at 18:23
  • That was the issue, I wasn't directing in search_terms.txt! Thanks muru, working as expected now – PaleSaint Feb 17 '16 at 18:25
  • @MelBurslan no, grep -r will be run on the current directory by default. That wasn't a problem. The -r flag makes grep run on all files in the current directory recursively. – terdon Feb 17 '16 at 18:37
2

There are a few issues here:

  1. The while loop isn't reading any input. The correct format is

    while read line; do ... ; done < input file
    

    Or

    some other command | while read ...
    

    Your loop is therefore hanging, waiting for input. You can test this by running your script and then typing anything and hitting enter (here, I entered foo):

    $ foo.sh 
    Performing grep searches..
    foo
    Searching for foo..
    

    You can improve this by adding a prompt to your read:

    while IFS='' read -p "Enter a search pattern: " -r line ...
    

    That will still run until you stop it with Ctrl+C though.

  2. The || [[ -n "$line" ]] (which means "OR the variable $line is not empty") is never executed. Since read hangs, the "OR" is never reached. I don't understand what you wanted it to do anyway. If you want to search for $line if $line is defined and use read if it is not, you'd need something like:

    if [[ -n "$line" ]]; then
         grep -r "$line" --exclude-dir=grep_results > ./grep_results/"$line"_infile.txt
    else
        while IFS='' read -p "Enter a search pattern: " -r line || [[ -n "$line" ]]; do
          grep -r "$line" --exclude-dir=grep_results > ./grep_results/"$line"_infile.txt
        done
    fi
    

    Here, if $line is not defined, you still need to enter it manually. A cleaner approach would be to either feed a file to the while loop:

    while IFS='' read -r line || [[ -n "$line" ]]; do
      grep -r "$line" --exclude-dir=grep_results > ./grep_results/"$line"_infile.txt
    done < list_of_patterns.txt
    
1
  • The intention was to direct list of patterns in a file at it - so multiple sets of patterns can be saved and used as and when. The || [[ -n "$line" ]] bit was there on recommendation from the answer to the question linked in my original post (prevents the last line from being ignored if it doesn't end with a \n (since read returns a non-zero exit code when it encounters EOF).) Your answer definitely helped me make sense of it though, thanks! – PaleSaint Feb 17 '16 at 18:46

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.