Bash set: Difference between revisions

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
 
(41 intermediate revisions by the same user not shown)
Line 3: Line 3:
* <tt>set</tt> man page http://linuxcommand.org/lc3_man_pages/seth.html
* <tt>set</tt> man page http://linuxcommand.org/lc3_man_pages/seth.html
* https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html
* https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html
* https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/


=Internal=
=Internal=


* [[bash#Built-In_Commands|bash]]
* [[bash#Built-In_Commands|bash]]
=Overview=
This page discusses the base set [[Bash#Built-In_Commands|builtin]].


=<tt>set</tt> and Positional Parameters=
=<tt>set</tt> and Positional Parameters=


<pre>
<syntaxhighlight lang='bash'>
arg="a b c"
arg="a b c"
set - ${arg}
set - ${arg}
</pre>
</syntaxhighlight>
 
assigns "a", "b", "c" to [[Bash_Parameters_and_Variables#Positional_Parameters_.241.2C_.242.2C_...|positional parameters]] $1, $2 and $3. The [[Bash_Built-In_Variables#IFS|IFS]] environment variable must be set to " ", otherwise the entire string, including spaces, will be assigned to $1. Note that this assignment totally overwrites the existing positional parameters, if any. '-' that follows the [[Bash_Concepts#Builtin|builtin]] signals the end of options and causes all remaining arguments to be assigned to the positional parameters. This prevents arguments that start with "--..." to be interpreted as  [[bash set#Overview|set]] arguments and to interfere with [[bash set#Overview|set]] function. If "-" is not specified, and the first of the space-separated arguments contains '--', set will try to interpret that sequence of characters and will produce:
<font size=-1>
set: --: invalid option
</font>
{{Warn|If ${arg} is empty, set - ${arg} is a noop and it does not override existing positional parameters. Use [[#Unset_Positional_Parameters|set --]] or equivalent to unset existent positional parameters, if ${arg} is empty.}}
 
An indexed array can be used to initialize positional parameters too:
 
<syntaxhighlight lang='bash'>
declare -a ARGS
ARGS=("a" "b" "c")
set - "${ARGS[@]}"
</syntaxhighlight>
 
{{Warn|If ${ARGS} is empty, set - "${ARGS[@]}" is a noop and it does not override existing positional parameters. Use [[#Unset_Positional_Parameters|set --]] or equivalent to unset existent positional parameters, if ${ARGS} is empty.}}
 
==Difference between - and -- ==
 
--
 
If no arguments follow this option, then the positional parameters are unset.  Otherwise, the positional parameters are set to the args, even if some of them begin with a -.
 
-
 
Signal the end of options, cause all remaining args to be assigned to the positional parameters.  The -x and -v options are turned off.  If there are no args, the positional parameters remain unchanged.
 
==Unset Positional Parameters==
 
set --


assigns "a", "b", "c" to [[Bash_Built-In_Variables#Positional_Parameters_.241.2C_.242.2C_...|positional parameters]] $1, $2 and $3. '-' that follows the builtin signals the end of options and causes all remaining arguments to be assigned to the positional parameters. This prevents arguments that start with "--..." to interfere with [[bash set#Overview|set]] function. If "-" is not specified, and the first of the space-separated arguments contains '--', set will try to interpret that sequence of characters and will produce:
Alternative:


  set: --: invalid option
  shift $#


==List Separator==
==List Separator==
Line 39: Line 74:
For more details about IFS see:
For more details about IFS see:


{{InternalBash_Built-In_Variables#IFS|IFS}}
{{Internal|Bash_Built-In_Variables#IFS|IFS}}
 
=<tt>-x</tt>=
 
After expanding each simple command and for, case and select commands, display the expanded value of PS4, followed by the command and its expanded arguments or associated word list.
 
Note that arguments get expanded before a command gets printed, which will cause the output to contain the actual argument values that were present at the time of execution.
 
Useful in debugging.
 
=<tt>+x</tt>=
 
Prevents commands from being echoed at stdout. It is useful to start a script with set +x in case sensitive credentials are specified in commands.
 
=<tt>set -o pipefail</tt>=
 
By default, bash only looks at the exit code of the last command of a [[Bash_Concepts#Pipeline|pipeline]].
<syntaxhighlight lang='bash'>
set -o pipefail
</syntaxhighlight>
sets the exit code of a pipeline to that of the rightmost command to exit with a non-zero status, or to zero if all commands of the pipeline exit successfully.
 
=<tt>-e</tt>=
 
The -e option will cause a bash script to exit immediately when a command fails, as opposite to the default behavior where the script just ignores the failing command and continues with the next line. The option does not react to failing commands that are part of conditional statements.
 
If -e is in effect and we want to protect against '''specific''' commands that fail, use this pattern:
 
<syntaxhighlight lang='bash'>
some_command_that_might_fail || true
</syntaxhighlight>
 
Note that using -e without [[#-E|-E]] will cause an ERR [[Trap|trap]] to not fire in certain scenarios.
 
=<tt>-E</tt>=
 
See [[#-e|-e]].
 
=<tt>-u</tt>=
 
This option causes the bash shell to treat unset variables as an error and exit immediately. Unset variables are a common cause of bugs in shell scripts, so having unset variables cause an immediate exit is often highly desirable behavior. -u handles [[Bash_Parameter_and_Variable_Expansion#Expand_to_a_Default_Value|${var:-alternative}]] gracefully.


=-x=
=<tt>-f|set -o noglob</tt>=
Disable file name generation (globbing).

Latest revision as of 00:56, 7 February 2022

External

Internal

Overview

This page discusses the base set builtin.

set and Positional Parameters

arg="a b c"
set - ${arg}

assigns "a", "b", "c" to positional parameters $1, $2 and $3. The IFS environment variable must be set to " ", otherwise the entire string, including spaces, will be assigned to $1. Note that this assignment totally overwrites the existing positional parameters, if any. '-' that follows the builtin signals the end of options and causes all remaining arguments to be assigned to the positional parameters. This prevents arguments that start with "--..." to be interpreted as set arguments and to interfere with set function. If "-" is not specified, and the first of the space-separated arguments contains '--', set will try to interpret that sequence of characters and will produce:

set: --: invalid option


If ${arg} is empty, set - ${arg} is a noop and it does not override existing positional parameters. Use set -- or equivalent to unset existent positional parameters, if ${arg} is empty.

An indexed array can be used to initialize positional parameters too:

declare -a ARGS
ARGS=("a" "b" "c")
set - "${ARGS[@]}"

If ${ARGS} is empty, set - "${ARGS[@]}" is a noop and it does not override existing positional parameters. Use set -- or equivalent to unset existent positional parameters, if ${ARGS} is empty.

Difference between - and --

--

If no arguments follow this option, then the positional parameters are unset. Otherwise, the positional parameters are set to the args, even if some of them begin with a -.

-

Signal the end of options, cause all remaining args to be assigned to the positional parameters. The -x and -v options are turned off. If there are no args, the positional parameters remain unchanged.

Unset Positional Parameters

set --

Alternative:

shift $#

List Separator

The default list separator is space. That can be changed by setting the value of the IFS variable before executing set.

Example:

arg="a,b,c"
IFS=","
set ${arg}

will identically assign "a", "b", "c" to positional parameters $1, $2 and $3.

Note you must set IFS back to whitespace after setting it to something else, so the basic shell function work as expected. This is done as shown here: restoring the default IFS value.

For more details about IFS see:

IFS

-x

After expanding each simple command and for, case and select commands, display the expanded value of PS4, followed by the command and its expanded arguments or associated word list.

Note that arguments get expanded before a command gets printed, which will cause the output to contain the actual argument values that were present at the time of execution.

Useful in debugging.

+x

Prevents commands from being echoed at stdout. It is useful to start a script with set +x in case sensitive credentials are specified in commands.

set -o pipefail

By default, bash only looks at the exit code of the last command of a pipeline.

set -o pipefail

sets the exit code of a pipeline to that of the rightmost command to exit with a non-zero status, or to zero if all commands of the pipeline exit successfully.

-e

The -e option will cause a bash script to exit immediately when a command fails, as opposite to the default behavior where the script just ignores the failing command and continues with the next line. The option does not react to failing commands that are part of conditional statements.

If -e is in effect and we want to protect against specific commands that fail, use this pattern:

 some_command_that_might_fail || true

Note that using -e without -E will cause an ERR trap to not fire in certain scenarios.

-E

See -e.

-u

This option causes the bash shell to treat unset variables as an error and exit immediately. Unset variables are a common cause of bugs in shell scripts, so having unset variables cause an immediate exit is often highly desirable behavior. -u handles ${var:-alternative} gracefully.

-f|set -o noglob

Disable file name generation (globbing).