Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the meaning of the parameter -e for bash shell command line?

Tags:

bash

shell

I have as bash shell script with header #!/bin/bash -e.

When I run the script, it will be interrupted after the grep command runs, but when I remove the parameter -e, then the script can be run normally. What is the meaning of parameter -e?

like image 271
Sam Ho Avatar asked Mar 31 '12 01:03

Sam Ho


People also ask

What is a bash parameter?

The parameter is used in bash to store data. Different types of data can be stored in the parameter, such as integer, string, array, etc. by using built-in declare keyword. The parameter can be a positional parameter, special parameter, and variable.

What is parameter in shell?

Shell Spscript parameters are the entities that are used to store variables in Shell. Among these parameters, the named spaces are there in the memory and they permit us to access these stored variables. Generally, there are two types of parameters. They are called variables and special parameters.

What does $# mean in bash script?

$# is the number of positional parameters passed to the script, shell, or shell function. This is because, while a shell function is running, the positional parameters are temporarily replaced with the arguments to the function. This lets functions accept and use their own positional parameters.


2 Answers

The -e option means "if any pipeline ever ends with a non-zero ('error') exit status, terminate the script immediately". Since grep returns an exit status of 1 when it doesn't find any match, it can cause -e to terminate the script even when there wasn't a real "error".

If you want to keep the -e option, but also have a grep command that might validly find no matches, you can append || : to the grep command. This means "or, if the grep command returns a non-zero exit status, run : (which does nothing)"; so the net effect is to disable -e for the grep command. So:

grep PATTERN FILE... || : 

Edited to add: The above approach discards every error: if grep returns 1 because it found no matches, that's ignored, but also if grep returns 2 because there was an error, that's ignored, and if grep isn't in the path (so Bash returns 127), that's ignored — and so on. So, rather than :, it's probably better to use a command that checks the result code and re-issues the error if it's something other than 1. For example:

grep PATTERN FILE || (( $? == 1 )) 

But this destroys the exit status; usually, when a failed command terminates a Bash script with -e, the script will return the command's exit-status, but in the above example, the script will just return 1. If (and only if) we care about that, we can fix it by write something like this:

grep PATTERN FILE || exit_code=$? if (( exit_code > 1 )) ; then     exit $exit_code fi 

(first line c/o dsummersl's comment).

At this point, it's probably best to create a shell function to handle this for us:

function grep_no_match_ok () {     local exit_code     grep "$@" || exit_code=$?     return $(( exit_code == 1 ? 0 : exit_code )) } 

(note the use of return rather than exit; we'll let -e handle the exiting when appropriate); this way, we can just write:

grep_no_match_ok PATTERN FILE     # won't kill script if no matches are found 

In fact, since we most likely want to use this function for all occurrences of grep in this script, we can actually just name the function grep:

function grep () {     local exit_code     command grep "$@" || exit_code=$?     return $(( exit_code == 1 ? 0 : exit_code )) }  grep PATTERN FILE     # won't kill script if no matches are found 

(note the use of command to bypass the shell function within its own body: we want the function to call the regular program grep, rather than to recurse infinitely).

like image 76
ruakh Avatar answered Oct 18 '22 04:10

ruakh


From the fine manual:

In addition to the single-character shell command-line options (see The Set Builtin), there are several multi-character options that you can use.

And then if we look at what set has to say:

-e
Exit immediately if a pipeline (see Pipelines), which may consist of a single simple command (see Simple Commands), a subshell command enclosed in parentheses (see Command Grouping), or one of the commands executed as part of a command list enclosed by braces (see Command Grouping) returns a non-zero status.

So when you say bash -e, if any command in the script fails (i.e. returns a non-zero exist status), then the whole script immediately fails. So your grep is returning a non-zero value because it isn't matching and that's shutting down the whole script if you specify -e when running bash.

like image 37
mu is too short Avatar answered Oct 18 '22 05:10

mu is too short