1

I'm new to bash scripts (and the *nix shell altogether) but I'm trying to write this script to make grepping a codebase easier.

I have written this

#!/bin/bash
args=("$@");
for arg in args
 grep arg * */* */*/* */*/*/* */*/*/*/*;
done

when I try to run it, this is what happens:

~/Work/richmond $ ./f.sh "\$_REQUEST\['a'\]"
./f.sh: line 4: syntax error near unexpected token `grep'
./f.sh: line 4: `       grep arg * */* */*/* */*/*/* */*/*/*/*;'
~/Work/richmond $

How do I do this properly?

And, I think a more important question is, how can I make grep recurse through subdirectories properly like this?

Any other tips and/or pitfalls with shell scripting and using bash in general would also be appreciated.

1
  • PS: You can get rid of one line by using for arg: It's a shortcut for for arg in "$@". Commented Sep 19, 2011 at 12:59

6 Answers 6

9

The syntax error is because you're missing do. As for searching recursively if your grep has the -R option you would do:

#!/bin/bash
for arg in "$@"; do
   grep -R "$arg" *
done

Otherwise you could use find:

#!/bin/bash
for arg in "$@"; do
   find . -exec grep "$arg" {} +
done

In the latter example, find will execute grep and replace the {} braces with the file names it finds, starting in the current directory ..

(Notice that I also changed arg to "$arg". You need the dollar sign to get the variable's value, and the quotes tell the shell to treat its value as one big word, even if $arg contains spaces or newlines.)

Sign up to request clarification or add additional context in comments.

1 Comment

When iterating over command line arguments, you can also omit the "$@" and write it as just "for arg; do ..."
3

On recusive grepping:

Depending on your grep version, you can pass -R to your grep command to have it search Recursively (in subdirectories).

Comments

1

The best solution is stated above, but try putting your statement in back ticks:

`grep ...`

1 Comment

There is no reason to use backticks (or the preferred $()) in the OP's script or in any version posted in answers so far. If he was assigning the result to a variable or using it in-line as an argument to another command, that would be different.
1

You should use 'find' plus 'xargs' to do the file searching.

for arg in "$@"
do
    find . -type f -print0 | xargs -0 grep "$arg" /dev/null
done

The '-print0' and '-0' options assume you're using GNU grep and ensure that the script works even if there are spaces or other unexpected characters in your path names. Using xargs like this is more efficient than having find execute it for each file; the /dev/null appears in the argument list so grep always reports the name of the file containing the match.

You might decide to simplify life - perhaps - by combining all the searches into one using either egrep or grep -E. An optimization would be to capture the output from find once and then feed that to xargs on each iteration.

Comments

0

Have a look at the findrepo script which may give you some pointers

Comments

0

If you just want a better grep and don't want to do anything yourself, use ack, which you can get at http://betterthangrep.com/.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.