8

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.

11

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 '*'
*
  • Thank you. That was it. It should have used double quotes instead of single quote. – Peter Jul 9 '14 at 20:36
4

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 \;
}

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.