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
?
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.
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.
$# 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.
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).
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With