Jake Schievink
Jake Schievink

Reputation: 409

zsh script [process complete] not returning back to shell

I wrote a zsh function to help me do some grepping at my job.

   function rgrep (){ 
if [ -n "$1" ] && [ -n "$2" ]
then
    exec grep -rnw $1 -r $2
elif [ -n "$1" ]
then
    exec grep -rnw $1 -r "./"
else
    echo "please enter one or two args"
fi  
}

Works great, however, grep finishes executing I don't get thrown back into the shell. it just hangs at [process complete] any ideas? I have the function in my .zshrc

Upvotes: 0

Views: 509

Answers (3)

Aaron Davies
Aaron Davies

Reputation: 1230

As a completely different approach, I like to build command shortcuts like this as minimal shell scripts, rather than functions (or aliases):

% echo 'grep -rwn "$@"' >rgrep
% chmod +x rgrep
% ./rgrep
Usage: grep [OPTION]... PATTERN [FILE]...
Try `grep --help' for more information.
% 

(This relies on a traditional behavior of Unix: executable text files without #! lines are considered shell scripts and are executed by /bin/sh. If that doesn't work on your system, or you need to run specifically under zsh, use an appropriate #! line.)

One of the main benefits of this approach is that shell scripts in a directory in your PATH are full citizens of the environment, not local to the current shell like functions and aliases. This means they can be used in situations where only executable files are viable commands, such as xargs, sudo, or remote invocation via ssh.

This doesn't provide the ability to give default arguments (or not easily, anyway), but IMAO the benefits outweigh the drawbacks. (And in the specific case of defaulting grep to search PWD recursively, the real solution is to install ack.)

Upvotes: 1

chepner
chepner

Reputation: 531155

In addition to getting rid of the unnecessary exec, you can remove the if statement as well.

function rgrep (){
    grep -rwn "${1:?please enter one or two args}" -r "${2:-./}"
}

If $1 is not set (or null valued), an error will be raised and the given message displayed. If $2 is not set, a default value of ./ will be used in its place.

Upvotes: 3

jmlemetayer
jmlemetayer

Reputation: 4952

Do not use exec as it replace the existing shell.

exec [-cl] [-a name] [command [arguments]]

If command is supplied, it replaces the shell without creating a new process. If the -l option is supplied, the shell places a dash at the beginning of the zeroth argument passed to command. This is what the login program does. The -c option causes command to be executed with an empty environment. If -a is supplied, the shell passes name as the zeroth argument to command. If no command is specified, redirections may be used to affect the current shell environment. If there are no redirection errors, the return status is zero; otherwise the return status is non-zero.

Try this instead:

rgrep ()
{ 
    if [ -n "$1" ] && [ -n "$2" ]
    then
        grep -rnw "$1" -r "$2"
    elif [ -n "$1" ]
    then
        grep -rnw "$1" -r "./"
    else
        echo "please enter one or two args"
    fi  
}

Upvotes: 3

Related Questions