9

I often have to do a recursive search in files. Tired of typing the whole "find/grep" combination all the time, I just created a script with the following line:

find . -name $1 -exec grep $2 {} + 2>/dev/null

The idea is that I should be able to run it as, for example:

myfind '*' hello

The problem is, when '*' gets passed into the script, the script is expanding it to each file in the directory.

I tried putting a quote around $1:

 find . -name '$1' -exec grep $2 {} + 2>/dev/null

However, this turns $1 into a literal string.

Would appreciate your help in finding the right syntax. Must be something simple that I am missing.

0

2 Answers 2

12

I've demonstrated the problem here:

$ pie() { echo $1; }; pie '*'
1 2 3 4 5 file

Expanded. Bother.

But the solution is quite simple. You just need to quote it but in a way that bash will understand. We use double-quotes. It will be replaced with the variable contents but it won't be expanded.

$ pie() { echo "$1"; }; pie '*'
*
1
  • Thank you. That was it. It should have used double quotes instead of single quote.
    – Peter
    Jul 9, 2014 at 20:36
7

You need to familiarize yourself with the basic rules concerning shell expansion of variables.

NAME="start"

IF you present $NAME to the shell it will be exanded to the string start

If you put single quotes around a string, the shell does not expand whatever is within the single quotes, so '$NAME' stays as $NAME

Now with double quotes, the shell expands the variable $NAME to the string start but the double quotes prevent what is known as file globbing.

What is file globbing you ask?

Well it you do

ls -l *

you expect the ls command to list all of the files. It is not ls which is converting * to all of the file names in the directory, but the shell.

Now say you had a file named * in your directory and you just wanted to list that file, then you could use either

ls -l '*' 

or

ls -l "*"

and both the single and double quotes prevent the shell from expanding the * to the list of files.

Globbing can also be turned off by doing

set noglob

Rather than having this simple find string as a separate shell script requiring a new shell to be invoked every time it is used, the more efficient way is to create is as a shell function fs (find_string)

function fs ()
{
 \find . -type f -name "${1}" -exec egrep --color "${2}" {} /dev/null \;
}

You must log in to answer this question.

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