Updated table formatting, call-outs, html comments, improper escapes.

This commit is contained in:
Sahal Ansari 2024-10-07 23:00:17 -05:00
parent de70cb886e
commit cd90135cce
70 changed files with 2304 additions and 2424 deletions

View File

@ -8,7 +8,7 @@
The `caller` builtin command is used to print execution frames of The `caller` builtin command is used to print execution frames of
subroutine calls. Without giving a framenumber, the topmost execution subroutine calls. Without giving a framenumber, the topmost execution
frame information is printed (\"who called me\") wile linenumber and frame information is printed ("who called me") wile linenumber and
filename. filename.
When an execution frame number is given (0 - topmost), the linenumber, When an execution frame number is given (0 - topmost), the linenumber,
@ -22,10 +22,10 @@ used in a loop (see the examples section below).
The code below defines a function `die` that is used to exit the The code below defines a function `die` that is used to exit the
program. It prints a list of execution frames, starting with the topmost program. It prints a list of execution frames, starting with the topmost
frame (0). The topmost frame is the \"caller of the die function\", in frame (0). The topmost frame is the "caller of the die function", in
this case function \"f1\". this case function "f1".
This way, you can print a \"stack trace\" for debugging or logging This way, you can print a "stack trace" for debugging or logging
purposes. purposes.
The code is made very simple, just to show the basic purposes. The code is made very simple, just to show the basic purposes.
@ -70,9 +70,9 @@ f3
[Bashdb](http://bashdb.sourceforge.net/) can assist in using some of [Bashdb](http://bashdb.sourceforge.net/) can assist in using some of
Bash's more advanced debug features. Bash's more advanced debug features.
- The Bash manpage and help text specifies that the argument to - The Bash manpage and help text specifies that the argument to
`caller` is an \"expr\" (whatever that means). Only an integer is `caller` is an "expr" (whatever that means). Only an integer is
actually allowed, with no special interpretation of an actually allowed, with no special interpretation of an
\"expression\" as far as we can tell. "expression" as far as we can tell.
## Portability considerations ## Portability considerations

View File

@ -37,7 +37,7 @@ Below, `[-+]X` indicates an attribute, use `-X` to set the attribute,
`[-+]A` make NAMEs associative arrays `[-+]A` make NAMEs associative arrays
`[-+]c` **Undocumented** convert NAMEs to \"capcase\" on assignment (makes the first letter upper-case and the rest lower). Requires Bash built with `-DCASEMOD_CAPCASE` `[-+]c` **Undocumented** convert NAMEs to "capcase" on assignment (makes the first letter upper-case and the rest lower). Requires Bash built with `-DCASEMOD_CAPCASE`
`-f` restrict action or display to function names and definitions (removing with `+f` is valid syntax, but leads to an error message) `-f` restrict action or display to function names and definitions (removing with `+f` is valid syntax, but leads to an error message)
@ -45,20 +45,20 @@ Below, `[-+]X` indicates an attribute, use `-X` to set the attribute,
`-g` create global variables when used in a shell function; otherwise ignored (by default, `declare` declares local scope variables when used in shell functions) `-g` create global variables when used in a shell function; otherwise ignored (by default, `declare` declares local scope variables when used in shell functions)
`[-+]i` make NAMEs have the \"integer\" attribute `[-+]i` make NAMEs have the "integer" attribute
`[-+]l` convert NAMEs to lower case on assignment (makes sure the variable contains only lower case letters) `[-+]l` convert NAMEs to lower case on assignment (makes sure the variable contains only lower case letters)
`[-+]n` make NAME a reference to the variable named by its value. Introduced in Bash 4.3-alpha.\ `[-+]n` make NAME a reference to the variable named by its value. Introduced in Bash 4.3-alpha.
\'\' \${!NAME}\'\' reveals the reference variable name, VALUE.\ ''`${!NAME}`'' reveals the reference variable name, VALUE.
Use `unset -n NAME` to unset the variable. (`unset -v NAME` unsets the VALUE variable.)\ Use `unset -n NAME` to unset the variable. (`unset -v NAME` unsets the VALUE variable.)
Use `[[ -R NAME ]]` to test if NAME has been set to a VALUE, another variable's name. Use `[[ -R NAME ]]` to test if NAME has been set to a VALUE, another variable's name.
`-p` display the attributes and value of each NAME `-p` display the attributes and value of each NAME
`[-+]r` make NAMEs readonly (removing with `+r` is valid syntax, but not possible) `[-+]r` make NAMEs readonly (removing with `+r` is valid syntax, but not possible)
`[-+]t` make NAMEs have the \"trace\" attribute (effective only for functions) `[-+]t` make NAMEs have the "trace" attribute (effective only for functions)
`[-+]u` convert NAMEs to upper case on assignment (makes sure the variable contains only upper case letters) `[-+]u` convert NAMEs to upper case on assignment (makes sure the variable contains only upper case letters)
@ -76,13 +76,13 @@ Below, `[-+]X` indicates an attribute, use `-X` to set the attribute,
!= 0 assignment to a readonly variable != 0 assignment to a readonly variable
!= 0 removing the readonly-attribute from a readonly variable != 0 removing the readonly-attribute from a readonly variable
!= 0 assignment to an array variable without the compound assignment syntax (`array=(...)`) != 0 assignment to an array variable without the compound assignment syntax (`array=(...)`)
!= 0 attempt to use `+a` to \"destroy\" an array != 0 attempt to use `+a` to "destroy" an array
!= 0 attemt to display a non-existent function with `-f` != 0 attemt to display a non-existent function with `-f`
## Notes ## Notes
Unix shells offer very few datatypes. Bash and some other shells extend Unix shells offer very few datatypes. Bash and some other shells extend
this by allowing \"attributes\" to be set on variable names. The only this by allowing "attributes" to be set on variable names. The only
attributes specified by POSIX are `export` and `readonly`, which are set attributes specified by POSIX are `export` and `readonly`, which are set
by their own dedicated builtins. Datatypes in bash have a few other by their own dedicated builtins. Datatypes in bash have a few other
interesting capabilities such as the ability to modify data on interesting capabilities such as the ability to modify data on
@ -92,23 +92,23 @@ assignment.
### Display defined functions ### Display defined functions
`declare -f` can be used to display all defined functions\... `declare -f` can be used to display all defined functions...
$ declare -f $ declare -f
foo () foo ()
{ {
echo "FOO is BAR" echo "FOO is BAR"
} }
world () world ()
{ {
echo "Hello World!" echo "Hello World!"
} }
\...or just a specific defined function. ...or just a specific defined function.
$ declare -f foo $ declare -f foo
foo () foo ()
{ {
echo "FOO is BAR" echo "FOO is BAR"
} }
@ -172,7 +172,7 @@ for details. ksh93 namerefs are much more powerful than Bash's.
considers `typeset` a special builtin, while Bash does not - even in considers `typeset` a special builtin, while Bash does not - even in
POSIX mode. If you use `typeset`, you should attempt to only use it POSIX mode. If you use `typeset`, you should attempt to only use it
in portable ways. in portable ways.
- **todo** nameref portability\... - **todo** nameref portability...
## See also ## See also

View File

@ -29,7 +29,7 @@ if given.
`\a` alert (bell) `\a` alert (bell)
`\b` backspace `\b` backspace
`\c` suppress further output `\c` suppress further output
`\e` `\e`
`\E` an escape character `\E` an escape character
`\f` form feed `\f` form feed
`\n` new line `\n` new line
@ -56,17 +56,14 @@ if given.
case `-n` is always treated as a string, and backslash escapes are case `-n` is always treated as a string, and backslash escapes are
interpreted by default. `dash` has the misfeature of following this interpreted by default. `dash` has the misfeature of following this
and interpreting escapes by default, but includes a `-n` feature for and interpreting escapes by default, but includes a `-n` feature for
suppressing newlines nevertheless.\ suppressing newlines nevertheless.
\
In practice, if you\'re able to assume a korn-like shell including In practice, if you're able to assume a korn-like shell including
bash, mksh, or zsh, `echo` when used in simple cases is generally bash, mksh, or zsh, `echo` when used in simple cases is generally
reliable. For example, in the very common situation in which echo is reliable. For example, in the very common situation in which echo is
supplied with a single argument and whose output is to have a supplied with a single argument and whose output is to have a
newline appended, using `echo` is considered common practice. newline appended, using `echo` is considered common practice.
```{=html}
<!-- -->
```
- **Never use options to `echo`! *Ever*!** Any time you feel tempted - **Never use options to `echo`! *Ever*!** Any time you feel tempted
to use `echo -e`, `-n`, or any other special feature of echo, **use to use `echo -e`, `-n`, or any other special feature of echo, **use
[printf](../../commands/builtin/printf.md) instead!** If portability is a [printf](../../commands/builtin/printf.md) instead!** If portability is a
@ -76,9 +73,6 @@ if given.
\$\'\...\' \'\'if targeting only shells that support this special \$\'\...\' \'\'if targeting only shells that support this special
quoting style. quoting style.
```{=html}
<!-- -->
```
- `ksh93` has a `print` command, which if coding specifically for - `ksh93` has a `print` command, which if coding specifically for
`ksh93` should be preferred over `echo`. `ksh93` should be preferred over `echo`.
[printf](../../commands/builtin/printf.md) still includes most of the [printf](../../commands/builtin/printf.md) still includes most of the

View File

@ -55,7 +55,7 @@ This code defines a set of identical functions using the supplied names.
### Using printf %q ### Using printf %q
The `printf %q` format string performs shell escaping on its arguments. The `printf %q` format string performs shell escaping on its arguments.
This makes `printf %q` the \"anti-eval\" - with each pass of a string This makes `printf %q` the "anti-eval" - with each pass of a string
through printf requiring another `eval` to peel off the escaping again. through printf requiring another `eval` to peel off the escaping again.
while (( ++n <= 5 )) || ! evalBall="eval $evalBall"; do while (( ++n <= 5 )) || ! evalBall="eval $evalBall"; do
@ -112,16 +112,11 @@ controlled carefully by the caller is a good way to use it.
`setopt POSIX_BUILTINS` -- looks like a regression). This works `setopt POSIX_BUILTINS` -- looks like a regression). This works
correctly in Bash POSIX mode, Dash, and mksh. correctly in Bash POSIX mode, Dash, and mksh.
```{=html}
<!-- -->
```
- `eval` is another one of the few Bash builtins with keyword-like - `eval` is another one of the few Bash builtins with keyword-like
conditional parsing of arguments that are in the form of compound conditional parsing of arguments that are in the form of compound
assignments. assignments.
```{=html}
<!-- -->
```
$ ( eval a=( a b\\ c d ); printf '<%s> ' "${a[@]}"; echo ) # Only works in Bash. $ ( eval a=( a b\\ c d ); printf '<%s> ' "${a[@]}"; echo ) # Only works in Bash.
<a> <b c> <d> <a> <b c> <d>
$ ( x=a; eval "$x"=( a b\\ c d ); printf '<%s> ' "${a[@]}"; echo ) # Argument is no longer in the form of a valid assignment, therefore ordinary parsing rules apply. $ ( x=a; eval "$x"=( a b\\ c d ); printf '<%s> ' "${a[@]}"; echo ) # Argument is no longer in the form of a valid assignment, therefore ordinary parsing rules apply.
@ -168,7 +163,7 @@ identical to those of [let](../../commands/builtin/let.md).
eval](http://mywiki.wooledge.org/BashFAQ/006#Assigning_indirect.2BAC8-reference_variables) eval](http://mywiki.wooledge.org/BashFAQ/006#Assigning_indirect.2BAC8-reference_variables)
- [More indirection via - [More indirection via
eval](http://fvue.nl/wiki/Bash:_Passing_variables_by_reference) eval](http://fvue.nl/wiki/Bash:_Passing_variables_by_reference)
- [Martin Väth's \"push\"](https://github.com/vaeth/push) -- - [Martin Väth's "push"](https://github.com/vaeth/push) --
`printf %q` work-alike for POSIX. `printf %q` work-alike for POSIX.
- [The \"magic alias\" - [The "magic alias"
hack](http://www.chiark.greenend.org.uk/~sgtatham/aliases.html) hack](http://www.chiark.greenend.org.uk/~sgtatham/aliases.html)

View File

@ -27,7 +27,7 @@ The `kill` command is a Bash builtin command instead of relying on the
external `kill` command of the operating system to external `kill` command of the operating system to
- be able to use shell job specifications instead of Unix process IDs - be able to use shell job specifications instead of Unix process IDs
- be able to send signals (\"kill something\") also, when your process - be able to send signals ("kill something") also, when your process
limit is reached limit is reached
### Options ### Options

View File

@ -10,8 +10,8 @@ The `let` builtin command evaluates each supplied word from left to
right as an [arithmetic expression](../../syntax/arith_expr.md) and returns an right as an [arithmetic expression](../../syntax/arith_expr.md) and returns an
exit code according to the truth value of the rightmost expression. exit code according to the truth value of the rightmost expression.
- 0 (TRUE) when `arg` evaluated to not 0 (arithmetic \"true\") - 0 (TRUE) when `arg` evaluated to not 0 (arithmetic "true")
- 1 (FALSE) when `arg` evaluated to 0 (arithmetic \"false\") - 1 (FALSE) when `arg` evaluated to 0 (arithmetic "false")
For this return code mapping, please see [this For this return code mapping, please see [this
section](../../syntax/arith_expr.md#arithmetic_expressions_and_return_codes). section](../../syntax/arith_expr.md#arithmetic_expressions_and_return_codes).
@ -50,7 +50,7 @@ used above only to illustrate how this precedence works. </WRAP>
Unlike `((`, being a simple command `let` has its own environment. In Unlike `((`, being a simple command `let` has its own environment. In
Bash, built-ins that can set variables process any arithmetic under Bash, built-ins that can set variables process any arithmetic under
their own environment, which makes the variable effectively \"local\" to their own environment, which makes the variable effectively "local" to
the builtin unless the variable is also set or modified by the builtin. the builtin unless the variable is also set or modified by the builtin.
This differs in other shells, such as ksh93, where environment This differs in other shells, such as ksh93, where environment
assignments to regular builtins are always local even if the variable is assignments to regular builtins are always local even if the variable is
@ -84,7 +84,7 @@ needed.
choose `let` over `((` expecting it to work in more places. choose `let` over `((` expecting it to work in more places.
- [expr(1)](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/expr.html#tag_20_42) - [expr(1)](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/expr.html#tag_20_42)
is a command one is likely to come across sooner or later. While it is a command one is likely to come across sooner or later. While it
is more \"standard\" than `let`, the above should always be is more "standard" than `let`, the above should always be
preferred. Both [arithmetic expansion](../../syntax/arith_expr.md)s and the preferred. Both [arithmetic expansion](../../syntax/arith_expr.md)s and the
`[` test operator are specified by POSIX(r) and satisfy almost all `[` test operator are specified by POSIX(r) and satisfy almost all
of expr's use-cases. Unlike `let`, `expr` cannot assign directly to of expr's use-cases. Unlike `let`, `expr` cannot assign directly to
@ -108,4 +108,4 @@ needed.
- Internal: [arithmetic evaluation compound - Internal: [arithmetic evaluation compound
command](../../syntax/ccmd/arithmetic_eval.md) command](../../syntax/ccmd/arithmetic_eval.md)
[^1]: \... [^1]: ...

View File

@ -30,17 +30,11 @@ way, and takes all the same options, with 3 exceptions:
have a builtin called `local`, but some such as `dash` and the have a builtin called `local`, but some such as `dash` and the
busybox shell do. busybox shell do.
```{=html}
<!-- -->
```
- The behavior of function scope is not defined by POSIX, however - The behavior of function scope is not defined by POSIX, however
local variables are implemented widely by bourne-like shells, and local variables are implemented widely by bourne-like shells, and
behavior differs substantially. Even the`dash` shell has local behavior differs substantially. Even the`dash` shell has local
variables. variables.
```{=html}
<!-- -->
```
- In ksh93, using POSIX-style function definitions, `typeset` doesn't - In ksh93, using POSIX-style function definitions, `typeset` doesn't
set `local` variables, but rather acts upon variables of the set `local` variables, but rather acts upon variables of the
next-outermost scope (e.g. setting attributes). Using `typeset` next-outermost scope (e.g. setting attributes). Using `typeset`
@ -48,8 +42,8 @@ way, and takes all the same options, with 3 exceptions:
variables follow roughly variables follow roughly
[lexical-scoping](http://community.schemewiki.org/?lexical-scope), [lexical-scoping](http://community.schemewiki.org/?lexical-scope),
except that functions themselves don't have scope, just like Bash. except that functions themselves don't have scope, just like Bash.
This means that even functions defined within a \"function's This means that even functions defined within a "function's
scope\" don't have access to non-local variables except through scope" don't have access to non-local variables except through
`namerefs`. `namerefs`.
## See also ## See also

View File

@ -14,7 +14,7 @@ This builtin is also accessible using the command name `readarray`.
handling standard input (the other being `read`). `mapfile` reads lines handling standard input (the other being `read`). `mapfile` reads lines
of standard input and assigns each to the elements of an indexed array. of standard input and assigns each to the elements of an indexed array.
If no array name is given, the default array name is `MAPFILE`. The If no array name is given, the default array name is `MAPFILE`. The
target array must be a \"normal\" integer indexed array. target array must be a "normal" integer indexed array.
`mapfile` returns success (0) unless an invalid option is given or the `mapfile` returns success (0) unless an invalid option is given or the
given array `ARRAY` is set readonly. given array `ARRAY` is set readonly.
@ -47,9 +47,9 @@ Here's a real-world example of interactive use borrowed from Gentoo
workflow. Xorg updates require rebuilding drivers, and the workflow. Xorg updates require rebuilding drivers, and the
Gentoo-suggested command is less than ideal, so let's Bashify it. The Gentoo-suggested command is less than ideal, so let's Bashify it. The
first command produces a list of packages, one per line. We can read first command produces a list of packages, one per line. We can read
those into the array named \"args\" using `mapfile`, stripping trailing those into the array named "args" using `mapfile`, stripping trailing
newlines with the \'-t\' option. The resulting array is then expanded newlines with the '`-t`' option. The resulting array is then expanded
into the arguments of the \"emerge\" command - an interface to Gentoo's into the arguments of the `emerge` command - an interface to Gentoo's
package manager. This type of usage can make for a safe and effective package manager. This type of usage can make for a safe and effective
replacement for xargs(1) in certain situations. Unlike xargs, all replacement for xargs(1) in certain situations. Unlike xargs, all
arguments are guaranteed to be passed to a single invocation of the arguments are guaranteed to be passed to a single invocation of the
@ -59,7 +59,7 @@ business.
# eix --only-names -IC x11-drivers | { mapfile -t args; emerge -av1 "${args[@]}" <&1; } # eix --only-names -IC x11-drivers | { mapfile -t args; emerge -av1 "${args[@]}" <&1; }
Note the use of command grouping to keep the emerge command inside the Note the use of command grouping to keep the emerge command inside the
pipe's subshell and within the scope of \"args\". Also note the unusual pipe's subshell and within the scope of "args". Also note the unusual
redirection. This is because the -a flag makes emerge interactive, redirection. This is because the -a flag makes emerge interactive,
asking the user for confirmation before continuing, and checking with asking the user for confirmation before continuing, and checking with
isatty(3) to abort if stdin isn't pointed at a terminal. Since stdin of isatty(3) to abort if stdin isn't pointed at a terminal. Since stdin of
@ -71,11 +71,11 @@ wiki: <http://mywiki.wooledge.org/BashFAQ/024>
### The callback ### The callback
This is one of the more unusual features of a Bash builtin. As far as This is one of the more unusual features of a Bash builtin. As far as
I\'m able to tell, the exact behavior is as follows: If defined, as each I'm able to tell, the exact behavior is as follows: If defined, as each
line is read, the code contained within the string argument to the -C line is read, the code contained within the string argument to the -C
flag is evaluated and executed *before* the assignment of each array flag is evaluated and executed *before* the assignment of each array
element. There are no restrictions to this string, which can be any element. There are no restrictions to this string, which can be any
arbitrary code, however, two additional \"words\" are automatically arbitrary code, however, two additional "words" are automatically
appended to the end before evaluation: the index, and corresponding line appended to the end before evaluation: the index, and corresponding line
of data to be assigned to the next array element. Since all this happens of data to be assigned to the next array element. Since all this happens
before assignment, the callback feature cannot be used to modify the before assignment, the callback feature cannot be used to modify the
@ -91,9 +91,9 @@ the appended words from printf.
Really, the intended usage is for the callback to just contain the name Really, the intended usage is for the callback to just contain the name
of a function, with the extra words passed to it as arguments. If of a function, with the extra words passed to it as arguments. If
you\'re going to use callbacks at all, this is probably the best way you're going to use callbacks at all, this is probably the best way
because it allows for easy access to the arguments with no ugly \"code because it allows for easy access to the arguments with no ugly "code
in a string\". in a string".
$ foo() { echo "|$1|"; }; mapfile -n 11 -c 2 -C 'foo' <file $ foo() { echo "|$1|"; }; mapfile -n 11 -c 2 -C 'foo' <file
|2| |2|
@ -121,13 +121,13 @@ illustrates the callback behavior:
Since redirects are syntactically allowed anywhere in a command, we put Since redirects are syntactically allowed anywhere in a command, we put
it before the printf to stay out of the way of additional arguments. it before the printf to stay out of the way of additional arguments.
Rather than opening \"outfile<n>\" for appending on each call by Rather than opening "outfile&lt;n&gt;" for appending on each call by
calculating the filename, open an FD for each first and calculate which calculating the filename, open an FD for each first and calculate which
FD to send output to by measuring the size of x mod 2. The zero-width FD to send output to by measuring the size of x mod 2. The zero-width
format specification is used to absorb the index number argument. format specification is used to absorb the index number argument.
Another variation might be to add each of these lines to the elements of Another variation might be to add each of these lines to the elements of
separate arrays. I\'ll leave dissecting this one as an exercise for the separate arrays. I'll leave dissecting this one as an exercise for the
reader. This is quite the hack but illustrates some interesting reader. This is quite the hack but illustrates some interesting
properties of printf -v and mapfile -C (which you should probably never properties of printf -v and mapfile -C (which you should probably never
use in real code). use in real code).
@ -147,7 +147,7 @@ use in real code).
This example based on yet another #bash question illustrates mapfile in This example based on yet another #bash question illustrates mapfile in
combination with read. The sample input is the heredoc to `main`. The combination with read. The sample input is the heredoc to `main`. The
goal is to build a \"struct\" based upon records in the input file made goal is to build a "struct" based upon records in the input file made
up of the numbers following the colon on each line. Every 3rd line is a up of the numbers following the colon on each line. Every 3rd line is a
key followed by 2 corresponding fields. The showRecord function takes a key followed by 2 corresponding fields. The showRecord function takes a
key and returns the record. key and returns the record.

View File

@ -1,19 +1,22 @@
# The printf command # The printf command
<div center round todo box 70%> FIXME Stranger, this is a very big !!! warning "FIXME"
topic that needs experience - please fill in missing information, extend This is a very big topic that needs experience - please fill in
the descriptions, and correct the details if you can! </div> <div missing information, extend the descriptions, and correct the details
center round tip 70%> [**Attention:**]{.underline} This is about the if you can!
Bash-builtin command `printf` - however, the description should be
nearly identical for an external command that follows POSIX(r).
[GNU Awk](http://www.gnu.org/software/gawk/manual/gawk.html#Printf) !!! info "Bash-Builtin"
expects a comma after the format string and between each of the This is about the Bash-builtin command `printf` - however, the
arguments of a **printf** command. For examples, see: [code description should be nearly identical for an external command that
snippet](../../printf?&.md#using_printf_inside_of_awk). </div> follows POSIX(r).
[GNU Awk](http://www.gnu.org/software/gawk/manual/gawk.html#Printf)
expects a comma after the format string and between each of
the arguments of a **printf** command. For examples, see: [code
snippet](#differences-from-awk-printf).
Unlike other documentations, I don't want to redirect you to the manual Unlike other documentations, I don't want to redirect you to the manual
page for the `printf()` C function family. However, if you\'re more page for the `printf()` C function family. However, if you're more
experienced, that should be the most detailed description for the format experienced, that should be the most detailed description for the format
strings and modifiers. strings and modifiers.
@ -28,7 +31,7 @@ successor for `echo` and has far more features and possibilities.
Beside other reasons, POSIX(r) has a very good argument to recommend it: Beside other reasons, POSIX(r) has a very good argument to recommend it:
Both historical main flavours of the `echo` command are mutual Both historical main flavours of the `echo` command are mutual
exclusive, they collide. A \"new\" command had to be invented to solve exclusive, they collide. A "new" command had to be invented to solve
the issue. the issue.
## Syntax ## Syntax
@ -50,27 +53,28 @@ argument!).
### Options ### Options
---------- ------------------------------------------------------------------------------------------------------------------------------- | Option | Description |
`-v VAR` If given, the output is assigned to the variable `VAR` instead of printed to `stdout` (comparable to `sprintf()` in some way) |--------|-------------|
---------- ------------------------------------------------------------------------------------------------------------------------------- |`-v VAR`|If given, the output is assigned to the variable `VAR` instead of printed to `stdout` (comparable to `sprintf()` in some way)|
The `-v` Option can't assign directly to array indexes in Bash versions The `-v` Option can't assign directly to array indexes in Bash versions
older than Bash 4.1. older than Bash 4.1.
<note warning> In versions newer than 4.1, one must be careful when !!! danger "Danger"
performing expansions into the first non-option argument of printf as In versions newer than 4.1, one must be careful when
this opens up the possibility of an easy code injection vulnerability. performing expansions into the first non-option argument of printf as
this opens up the possibility of an easy code injection vulnerability.
$ var='-vx[$(echo hi >&2)]'; printf "$var" hi; declare -p x $ var='-vx[$(echo hi >&2)]'; printf "$var" hi; declare -p x
hi hi
declare -a x='([0]="hi")' declare -a x='([0]="hi")'
\...where the echo can of course be replaced with any arbitrary command. ...where the echo can of course be replaced with any arbitrary command.
If you must, either specify a hard-coded format string or use -- to If you must, either specify a hard-coded format string or use -- to
signal the end of options. The exact same issue also applies to signal the end of options. The exact same issue also applies to
[read](../../commands/builtin/read.md), and a similar one to [read](../../commands/builtin/read.md), and a similar one to
[mapfile](../../commands/builtin/mapfile.md), though performing expansions into [mapfile](../../commands/builtin/mapfile.md), though performing expansions into
their arguments is less common. </note> their arguments is less common.
### Arguments ### Arguments
@ -78,16 +82,16 @@ Of course in shell-meaning the arguments are just strings, however, the
common C-notations plus some additions for number-constants are common C-notations plus some additions for number-constants are
recognized to give a number-argument to `printf`: recognized to give a number-argument to `printf`:
Number-Format Description | Number-Format | Description |
--------------- ------------------------------------------------------------------------------------------------------------------------ |----------------|--------------|
`N` A normal decimal number |`N`|A normal decimal number|
`0N` An octal number |`0N`|An octal number|
`0xN` A hexadecimal number |`0xN`|A hexadecimal number|
`0XN` A hexadecimal number |`0XN`|A hexadecimal number|
`"X` (a literal double-quote infront of a character): interpreted as number (underlying codeset) **don't forget escaping** |`"X`|(a literal double-quote infront of a character): interpreted as number (underlying codeset) **don't forget escaping**|
`'X` (a literal single-quote infront of a character): interpreted as number (underlying codeset) **don't forget escaping** |`'X`|(a literal single-quote infront of a character): interpreted as number (underlying codeset) **don't forget escaping**|
[**If more arguments than format specifiers**]{.underline} are present, <u>**If more arguments than format specifiers**</u> are present,
then the format string is re-used until the last argument is then the format string is re-used until the last argument is
interpreted. If fewer format specifiers than arguments are present, then interpreted. If fewer format specifiers than arguments are present, then
number-formats are set to zero, while string-formats are set to null number-formats are set to zero, while string-formats are set to null
@ -97,15 +101,15 @@ Take care to avoid [word splitting](../../syntax/expansion/wordsplit.md), as
accidentally passing the wrong number of arguments can produce wildly accidentally passing the wrong number of arguments can produce wildly
different and unexpected results. See [this article](../../syntax/words.md). different and unexpected results. See [this article](../../syntax/words.md).
<note warning> [**Again, attention:**]{.underline} When a numerical !!! danger "Attention"
format expects a number, the internal `printf`-command will use the When a numerical
common Bash arithmetic rules regarding the base. A command like the format expects a number, the internal `printf`-command will use the
following example **will** throw an error, since `08` is not a valid common Bash arithmetic rules regarding the base. A command like the
octal number (`00` to `07`!): following example **will** throw an error, since `08` is not a valid
octal number (`00` to `07`!):
printf '%d\n' 08 printf '%d\n' 08
</note>
### Format strings ### Format strings
@ -115,7 +119,7 @@ family. Only format specifiers that end in one of the letters
To print a literal `%` (percent-sign), use `%%` in the format string. To print a literal `%` (percent-sign), use `%%` in the format string.
[**Again:**]{.underline} Every format specifier expects an associated <u>**Again:**</u> Every format specifier expects an associated
argument provided! argument provided!
These specifiers have different names, depending who you ask. But they These specifiers have different names, depending who you ask. But they
@ -124,30 +128,30 @@ all mean the same: A placeholder for data with a specified format:
- format placeholder - format placeholder
- conversion specification - conversion specification
- formatting token - formatting token
- \... - ...
Format Description | Format | Description |
-------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |-------------|----------------|
`%b` Print the associated argument while interpreting backslash escapes in there |`%b`|Print the associated argument while interpreting backslash escapes in there|
`%q` Print the associated argument **shell-quoted**, reusable as input |`%q`|Print the associated argument **shell-quoted**, reusable as input|
`%d` Print the associated argument as **signed decimal** number |`%d`|Print the associated argument as **signed decimal** number|
`%i` Same as `%d` |`%i`|Same as `%d`|
`%o` Print the associated argument as **unsigned octal** number |`%o`|Print the associated argument as **unsigned octal** number|
`%u` Print the associated argument as **unsigned decimal** number |`%u`|Print the associated argument as **unsigned decimal** number|
`%x` Print the associated argument as **unsigned hexadecimal** number with lower-case hex-digits (a-f) |`%x`|Print the associated argument as **unsigned hexadecimal** number with lower-case hex-digits (a-f)|
`%X` Same as `%x`, but with upper-case hex-digits (A-F) |`%X`|Same as `%x`, but with upper-case hex-digits (A-F)|
`%f` Interpret and print the associated argument as **floating point** number |`%f`|Interpret and print the associated argument as **floating point** number|
`%e` Interpret the associated argument as **double**, and print it in `<N>±e<N>` format |`%e`|Interpret the associated argument as **double**, and print it in `<N>±e<N>` format
`%E` Same as `%e`, but with an upper-case `E` in the printed format |`%E`|Same as `%e`, but with an upper-case `E` in the printed format|
`%g` Interprets the associated argument as **double**, but prints it like `%f` or `%e` |`%g`|Interprets the associated argument as **double**, but prints it like `%f` or `%e`
`%G` Same as `%g`, but print it like `%E` |`%G`|Same as `%g`, but print it like `%E`|
`%c` Interprets the associated argument as **char**: only the first character of a given argument is printed |`%c`|Interprets the associated argument as **char**: only the first character of a given argument is printed|
`%s` Interprets the associated argument literally as string |`%s`|Interprets the associated argument literally as string|
`%n` Assigns the number of characters printed so far to the variable named in the corresponding argument. Can't specify an array index. If the given name is already an array, the value is assigned to the zeroth element. |`%n`|Assigns the number of characters printed so far to the variable named in the corresponding argument. Can't specify an array index. If the given name is already an array, the value is assigned to the zeroth element.|
`%a` Interprets the associated argument as **double**, and prints it in the form of a C99 [hexadecimal floating-point literal](http://www.exploringbinary.com/hexadecimal-floating-point-constants/). |`%a`|Interprets the associated argument as **double**, and prints it in the form of a C99 [hexadecimal floating-point literal](http://www.exploringbinary.com/hexadecimal-floating-point-constants/).|
`%A` Same as `%a`, but print it like `%E` |`%A`|Same as `%a`, but print it like `%E`|
`%(FORMAT)T` output the date-time string resulting from using `FORMAT` as a format string for `strftime(3)`. The associated argument is the number of seconds since Epoch, or `-1` (current time) or `-2` (shell startup time). If no corresponding argument is supplies, the current time is used as default |`%(FORMAT)T`|output the date-time string resulting from using `FORMAT` as a format string for `strftime(3)`. The associated argument is the number of seconds since Epoch, or `-1` (current time) or `-2` (shell startup time). If no corresponding argument is supplies, the current time is used as default|
`%%` No conversion is done. Produces a `%` (percent sign) |`%%`|No conversion is done. Produces a `%` (percent sign)|
Some of the mentioned format specifiers can modify their behaviour by Some of the mentioned format specifiers can modify their behaviour by
getting a format modifier: getting a format modifier:
@ -162,26 +166,26 @@ introductory `%` and the character that specifies the format:
#### Field and printing modifiers #### Field and printing modifiers
Field output format |Field | output format|
--------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |-------|-------------|
`<N>` **Any number**: Specifies a **minimum field width**, if the text to print is shorter, it's padded with spaces, if the text is longer, the field is expanded |`<N>`|**Any number**: Specifies a **minimum field width**, if the text to print is shorter, it's padded with spaces, if the text is longer, the field is expanded|
`.` **The dot**: Together with a field width, the field is **not** expanded when the text is longer, the text is truncated instead. \"`%.s`\" is an undocumented equivalent for \"`%.0s`\", which will force a field width of zero, effectively hiding the field from output |`.`|**The dot**: Together with a field width, the field is **not** expanded when the text is longer, the text is truncated instead. "`%.s`" is an undocumented equivalent for "`%.0s`", which will force a field width of zero, effectively hiding the field from output|
`*` **The asterisk**: the width is given as argument before the string or number. Usage (the \"`*`\" corresponds to the \"`20`\"): `printf "%*s\n" 20 "test string"` |`*`|**The asterisk**: the width is given as argument before the string or number. Usage (the "`*`" corresponds to the "`20`"): `printf "%*s\n" 20 "test string"`|
`#` \"Alternative format\" for numbers: see table below |`#`|"Alternative format" for numbers: see table below|
`-` **Left-bound** text printing in the field (standard is **right-bound**) |`-`|**Left-bound** text printing in the field (standard is **right-bound**)|
`0` Pads numbers with zeros, not spaces |`0`|Pads numbers with zeros, not spaces|
`<space>` Pad a positive number with a space, where a minus (`-`) is for negative numbers |`<space>`|Pad a positive number with a space, where a minus (`-`) is for negative numbers|
`+` Prints all numbers **signed** (`+` for positive, `-` for negative) |`+`|Prints all numbers **signed** (`+` for positive, `-` for negative)|
`'` For decimal conversions, the thousands grouping separator is applied to the integer portion of the output according to the current LC_NUMERIC |`'`|For decimal conversions, the thousands grouping separator is applied to the integer portion of the output according to the current LC_NUMERIC|
[**The \"alternative format\" modifier `#`:**]{.underline} <u>**The "alternative format" modifier `#`:**</u>
Alternative Format |Alternative|Format|
-------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------- |-----------|------|
`%#o` The octal number is printed with a leading zero, unless it's zero itself |`%#o`|The octal number is printed with a leading zero, unless it's zero itself|
`%#x`, `%#X` The hex number is printed with a leading \"`0x`\"/\"`0X`\", unless it's zero |`%#x`, `%#X`|The hex number is printed with a leading "`0x`"/"`0X`", unless it's zero|
`%#g`, `%#G` The float number is printed with **trailing zeros** until the number of digits for the current precision is reached (usually trailing zeros are not printed) |`%#g`, `%#G`|The float number is printed with **trailing zeros** until the number of digits for the current precision is reached (usually trailing zeros are not printed)|
all number formats except `%d`, `%o`, `%x`, `%X` Always print a decimal point in the output, even if no digits follow it |all number formats except `%d`, `%o`, `%x`, `%X`|Always print a decimal point in the output, even if no digits follow it|
#### Precision #### Precision
@ -204,30 +208,30 @@ number of digits to print (zero-padding!).
These are interpreted if used anywhere in the format string, or in an These are interpreted if used anywhere in the format string, or in an
argument corresponding to a `%b` format. argument corresponding to a `%b` format.
Code Description |Code|Description|
---------------- --------------------------------------------------------------------------------------------------------------------------- |----|-----------|
`\\` Prints the character `\` (backslash) |`\\`|Prints the character `\` (backslash)|
`\a` Prints the alert character (ASCII code 7 decimal) |`\a`|Prints the alert character (ASCII code 7 decimal)|
`\b` Prints a backspace |`\b`|Prints a backspace|
`\f` Prints a form-feed |`\f`|Prints a form-feed|
`\n` Prints a newline |`\n`|Prints a newline|
`\r` Prints a carriage-return |`\r`|Prints a carriage-return|
`\t` Prints a horizontal tabulator |`\t`|Prints a horizontal tabulator|
`\v` Prints a vertical tabulator |`\v`|Prints a vertical tabulator|
`\"` Prints a `'` |`\"`|Prints a `'`|
`\?` Prints a `?` |`\?`|Prints a `?`|
`<NNN>` Interprets `<NNN>` as **octal** number and prints the corresponding character from the character set |`<NNN>`|Interprets `<NNN>` as **octal** number and prints the corresponding character from the character set|
`\0<NNN>` same as `<NNN>` |`\0<NNN>`|same as `<NNN>`|
`\x<NNN>` Interprets `<NNN>` as **hexadecimal** number and prints the corresponding character from the character set (**3 digits**) |`\x<NNN>`|Interprets `<NNN>` as **hexadecimal** number and prints the corresponding character from the character set (**3 digits**)|
`\u<NNNN>` same as `\x<NNN>`, but **4 digits** |`\u<NNNN>`|same as `\x<NNN>`, but **4 digits**|
`\U<NNNNNNNN>` same as `\x<NNN>`, but **8 digits** |`\U<NNNNNNNN>`|same as `\x<NNN>`, but **8 digits**|
The following additional escape and extra rules apply only to arguments The following additional escape and extra rules apply only to arguments
associated with a `%b` format: associated with a `%b` format:
------ ------------------------------------------------------------------------------------------------------------------------------------------------------------- |Escape Rule|Description|
`\c` Terminate output similarly to the `\c` escape used by `echo -e`. printf produces no additional output after coming across a `\c` escape in a `%b` argument. |-----------|-----------|
------ ------------------------------------------------------------------------------------------------------------------------------------------------------------- |`\c`|Terminate output similarly to the `\c` escape used by `echo -e`. printf produces no additional output after coming across a `\c` escape in a `%b` argument.|
- Backslashes in the escapes: `\'`, `\"`, and `\?` are not removed. - Backslashes in the escapes: `\'`, `\"`, and `\?` are not removed.
- Octal escapes beginning with `\0` may contain up to four digits. - Octal escapes beginning with `\0` may contain up to four digits.
@ -267,18 +271,17 @@ This small loop prints all numbers from 0 to 127 in
- octal - octal
- hex - hex
```{=html} ```bash
<!-- --> for ((x=0; x <= 127; x++)); do
printf '%3d | %04o | 0x%02x\n' "$x" "$x" "$x"
done
``` ```
for ((x=0; x <= 127; x++)); do
printf '%3d | %04o | 0x%02x\n' "$x" "$x" "$x"
done
### Ensure well-formatted MAC address ### Ensure well-formatted MAC address
This code here will take a common MAC address and rewrite it into a This code here will take a common MAC address and rewrite it into a
well-known format (regarding leading zeros or upper/lowercase of the hex well-known format (regarding leading zeros or upper/lowercase of the hex
digits, \...): digits, ...):
the_mac="0:13:ce:7:7a:ad" the_mac="0:13:ce:7:7a:ad"
@ -375,29 +378,23 @@ readability.
- The a, A, e, E, f, F, g, and G conversions are supported by Bash, - The a, A, e, E, f, F, g, and G conversions are supported by Bash,
but not required by POSIX. but not required by POSIX.
```{=html}
<!-- -->
```
- There is no wide-character support (wprintf). For instance, if you - There is no wide-character support (wprintf). For instance, if you
use `%c`, you\'re actually asking for the first byte of the use `%c`, you're actually asking for the first byte of the
argument. Likewise, the maximum field width modifier (dot) in argument. Likewise, the maximum field width modifier (dot) in
combination with `%s` goes by bytes, not characters. This limits combination with `%s` goes by bytes, not characters. This limits
some of printf's functionality to working with ascii only. ksh93's some of printf's functionality to working with ascii only. ksh93's
`printf` supports the `L` modifier with `%s` and `%c` (but so far `printf` supports the `L` modifier with `%s` and `%c` (but so far
not `%S` or `%C`) in order to treat precision as character width, not `%S` or `%C`) in order to treat precision as character width,
not byte count. zsh appears to adjust itself dynamically based upon not byte count. zsh appears to adjust itself dynamically based upon
`LANG` and `LC_CTYPE`. If `LC_CTYPE=C`, zsh will throw \"character `LANG` and `LC_CTYPE`. If `LC_CTYPE=C`, zsh will throw "character
not in range\" errors, and otherwise supports wide characters not in range" errors, and otherwise supports wide characters
automatically if a variable-width encoding is set for the current automatically if a variable-width encoding is set for the current
locale. locale.
```{=html}
<!-- -->
```
- Bash recognizes and skips over any characters present in the length - Bash recognizes and skips over any characters present in the length
modifiers specified by POSIX during format string parsing. modifiers specified by POSIX during format string parsing.
``` c|builtins/printf.def ``` c title="builtins/printf.def"
#define LENMODS "hjlLtz" #define LENMODS "hjlLtz"
... ...
/* skip possible format modifiers */ /* skip possible format modifiers */
@ -405,7 +402,6 @@ modstart = fmt;
while (*fmt && strchr (LENMODS, *fmt)) while (*fmt && strchr (LENMODS, *fmt))
fmt++; fmt++;
``` ```
- mksh has no built-in printf by default (usually). There is an - mksh has no built-in printf by default (usually). There is an
unsupported compile-time option to include a very poor, basically unsupported compile-time option to include a very poor, basically
unusable implementation. For the most part you must rely upon the unusable implementation. For the most part you must rely upon the
@ -414,36 +410,32 @@ fmt++;
a new parameter expansion in the form of `${name@Q}` which fills the a new parameter expansion in the form of `${name@Q}` which fills the
role of `printf %q` -- expanding in a shell-escaped format. role of `printf %q` -- expanding in a shell-escaped format.
```{=html}
<!-- -->
```
- ksh93 optimizes builtins run from within a command substitution and - ksh93 optimizes builtins run from within a command substitution and
which have no redirections to run in the shell's process. Therefore which have no redirections to run in the shell's process. Therefore
the `printf -v` functionality can be closely matched by the `printf -v` functionality can be closely matched by
`var=$(printf ...)` without a big performance hit. `var=$(printf ...)` without a big performance hit.
```{=html} ```bash
<!-- --> # Illustrates Bash-like behavior. Redefining printf is usually unnecessary / not recommended.
function printf {
case $1 in
-v)
shift
nameref x=$1
shift
x=$(command printf "$@")
;;
*)
command printf "$@"
esac
}
builtin cut
print $$
printf -v 'foo[2]' '%d\n' "$(cut -d ' ' -f 1 /proc/self/stat)"
typeset -p foo
# 22461
# typeset -a foo=([2]=22461)
``` ```
# Illustrates Bash-like behavior. Redefining printf is usually unnecessary / not recommended.
function printf {
case $1 in
-v)
shift
nameref x=$1
shift
x=$(command printf "$@")
;;
*)
command printf "$@"
esac
}
builtin cut
print $$
printf -v 'foo[2]' '%d\n' "$(cut -d ' ' -f 1 /proc/self/stat)"
typeset -p foo
# 22461
# typeset -a foo=([2]=22461)
- The optional Bash loadable `print` may be useful for ksh - The optional Bash loadable `print` may be useful for ksh
compatibility and to overcome some of compatibility and to overcome some of
@ -455,10 +447,6 @@ fmt++;
only `-Rrnfu` are actually functional. Internally, `-p` is a noop only `-Rrnfu` are actually functional. Internally, `-p` is a noop
(it doesn't tie in with Bash coprocs at all), and `-s` only sets a (it doesn't tie in with Bash coprocs at all), and `-s` only sets a
flag but has no effect. `-Cev` are unimplemented. flag but has no effect. `-Cev` are unimplemented.
```{=html}
<!-- -->
```
- Assigning to variables: The `printf -v` way is slightly different to - Assigning to variables: The `printf -v` way is slightly different to
the way using command-substitution. [Command the way using command-substitution. [Command
substitution](../../syntax/expansion/cmdsubst.md) removes trailing newlines substitution](../../syntax/expansion/cmdsubst.md) removes trailing newlines

View File

@ -8,7 +8,7 @@
## Description ## Description
The `read` builtin reads **one line** of data (text, user input, \...) The `read` builtin reads **one line** of data (text, user input, ...)
from standard input or a supplied filedescriptor number into one or more from standard input or a supplied filedescriptor number into one or more
variables named by `<NAME...>`. variables named by `<NAME...>`.
@ -50,7 +50,7 @@ line is read). That means the timeout can occur during input, too.
`-p <PROMPT>` the prompt string `<PROMPT>` is output (without a trailing automatic newline) before the read is performed `-p <PROMPT>` the prompt string `<PROMPT>` is output (without a trailing automatic newline) before the read is performed
`-r` raw input - **disables** interpretion of **backslash escapes** and **line-continuation** in the read data `-r` raw input - **disables** interpretion of **backslash escapes** and **line-continuation** in the read data
`-s` secure input - don't echo input if on a terminal (passwords!) `-s` secure input - don't echo input if on a terminal (passwords!)
`-t <TIMEOUT>` wait for data `<TIMEOUT>` seconds, then quit (exit code 1). Fractional seconds (\"5.33\") are allowed since Bash 4. A value of 0 immediately returns and indicates if data is waiting in the exit code. Timeout is indicated by an exit code greater than 128. If timeout arrives before data is read completely (before end-of-line), the partial data is saved. `-t <TIMEOUT>` wait for data `<TIMEOUT>` seconds, then quit (exit code 1). Fractional seconds ("5.33") are allowed since Bash 4. A value of 0 immediately returns and indicates if data is waiting in the exit code. Timeout is indicated by an exit code greater than 128. If timeout arrives before data is read completely (before end-of-line), the partial data is saved.
`-u <FD>` use the filedescriptor number `<FD>` rather than `stdin` (0) `-u <FD>` use the filedescriptor number `<FD>` rather than `stdin` (0)
When both, `-a <ARRAY>` and a variable name `<NAME>` is given, then the When both, `-a <ARRAY>` and a variable name `<NAME>` is given, then the
@ -134,12 +134,12 @@ from a file and print them on the terminal.
done <"$1" done <"$1"
} }
[**Note:**]{.underline} Here, `read -r` and the default `REPLY` is used, <u>**Note:**</u> Here, `read -r` and the default `REPLY` is used,
because we want to have the real literal line, without any mangeling. because we want to have the real literal line, without any mangeling.
`printf` is used, because (depending on settings), `echo` may interpret `printf` is used, because (depending on settings), `echo` may interpret
some baskslash-escapes or switches (like `-n`). some baskslash-escapes or switches (like `-n`).
### Press any key\... ### Press any key...
Remember the MSDOS `pause` command? Here's something similar: Remember the MSDOS `pause` command? Here's something similar:
@ -236,7 +236,7 @@ be different between each field:
### Ask for a path with a default value ### Ask for a path with a default value
[**Note:**]{.underline} The `-i` option was introduced with Bash 4 <u>**Note:**</u> The `-i` option was introduced with Bash 4
read -e -p "Enter the path to the file: " -i "/usr/local/etc/" FILEPATH read -e -p "Enter the path to the file: " -i "/usr/local/etc/" FILEPATH

View File

@ -15,23 +15,23 @@ readonly variables.
### Options ### Options
Option Description |Option|Description|
-------- ------------------------------------------------------------------------------------------------------------------------ |-|-|
`-a` refer to normal arrays |`-a`|refer to normal arrays|
`-A` refer to associative arrays |`-A`|refer to associative arrays|
`-f` refer to functions |`-f`|refer to functions|
`-p` print all read-only variables or functions, `-a`, `-A` and `-f` can be used to filter. The output is reusable as input |`-p`|print all read-only variables or functions, `-a`, `-A` and `-f` can be used to filter. The output is reusable as input|
An argument of `--` disables further option processing. An argument of `--` disables further option processing.
### Return status ### Return status
Status Reason |Status|Reason|
-------- -------------------------------- |-|-|
0 no error |0|no error|
!=0 invalid option |!=0|invalid option|
!=0 invalid combination of options |!=0|invalid combination of options|
!=0 a given `NAME` is invalid |!=0|a given `NAME` is invalid|
## Examples ## Examples

View File

@ -21,9 +21,9 @@ There are no options.
If everything is okay, the `return` command doesn't come back. If it If everything is okay, the `return` command doesn't come back. If it
comes back, there was a problem in doing the return. comes back, there was a problem in doing the return.
Status Reason |Status|Reason|
-------- ------------------------------------------------------------------------- |-|-|
1 `return` was called while not being in a shell function or sourced file |1|`return` was called while not being in a shell function or sourced file|
## Examples ## Examples

View File

@ -1,6 +1,7 @@
# The set builtin command # The set builtin command
FIXME incomplete - text, examples, maybe extended description !!! warning "FIXME"
incomplete text, examples, maybe extended description
## Synopsis ## Synopsis
@ -24,38 +25,38 @@ All attributes below can be switched on using `-X` and switched off
using `+X`. This is done because of the historical meaning of the `-` to using `+X`. This is done because of the historical meaning of the `-` to
set flags (true for most commands on UNIX(r)). set flags (true for most commands on UNIX(r)).
Flag Optionname Description |Flag|Optionname|Description|
------ ---------------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |----|----------|-----------|
`-a` `allexport` Automatically mark new and altered variables to be exported to subsequent environments. |`-a`|`allexport`|Automatically mark new and altered variables to be exported to subsequent environments.|
`-b` `notify` Don't wait for the next prompt to print when showing the reports for a terminated background job (only with job control) |`-b`|`notify`|Don't wait for the next prompt to print when showing the reports for a terminated background job (only with job control)|
`-e` `errexit` When set, the shell exits when a simple command in a command list exits non-zero (`FALSE`). This is not done in situations, where the exit code is already checked (`if`, `while`, `until`, `||`, `&&`) |`-e`|`errexit`|When set, the shell exits when a simple command in a command list exits non-zero (`FALSE`). This is not done in situations, where the exit code is already checked (`if`, `while`, `until`, `||`, `&&`)|
`-f` `noglob` Disable [pathname expansion](../../syntax/expansion/globs.md) (globbing) |`-f`|`noglob`|Disable [pathname expansion](../../syntax/expansion/globs.md) (globbing)|
`-h` `hashall` Remembers the location of commands when they\'re called (hashing). Enabled by default. |`-h`|`hashall`|Remembers the location of commands when they're called (hashing). Enabled by default.|
`-k` `keyword` Allows to place environment-assignments everywhere in the commandline, not only infront of the called command. |`-k`|`keyword`|Allows to place environment-assignments everywhere in the commandline, not only infront of the called command.|
`-m` `monitor` **Monitor mode**. With job control, a short descriptive line is printed when a backgroud job ends. Default is \"on\" for interactive shells (with job control). |`-m`|`monitor`|**Monitor mode**. With job control, a short descriptive line is printed when a backgroud job ends. Default is "on" for interactive shells (with job control).|
`-n` `noexec` Read and parse but **do not execute commands** - useful for checking scripts for syntax errors. Ignored by interactive shells. |`-n`|`noexec`|Read and parse but **do not execute commands** - useful for checking scripts for syntax errors. Ignored by interactive shells.|
`-o` Set/unset attributes with long option names, e.g. `set -o noglob`. The long option names are in the second column of this table. If no option name is given, all options are printed with their current status. |`-o`||Set/unset attributes with long option names, e.g. `set -o noglob`. The long option names are in the second column of this table. If no option name is given, all options are printed with their current status.|
`-p` `privileged` Turn on privileged mode. |`-p`|`privileged`|Turn on privileged mode.|
`-t` `onecmd` Exit after reading and executing **one** command. |`-t`|`onecmd`|Exit after reading and executing **one** command.|
`-u` `nounset` Treat unset variables as an error when performing parameter expansion. Non-interactive shells exit on this error. |`-u`|`nounset`|Treat unset variables as an error when performing parameter expansion. Non-interactive shells exit on this error.|
`-v` `verbose` Print shell input lines as they are read - useful for debugging. |`-v`|`verbose`|Print shell input lines as they are read - useful for debugging.|
`-x` `xtrace` Print commands just before execution - with all expansions and substitutions done, and words marked - useful for debugging. |`-x`|`xtrace`|Print commands just before execution - with all expansions and substitutions done, and words marked - useful for debugging.|
`-B` `braceexpand` The shell performs [brace expansion](../../syntax/expansion/brace.md) This is on by default. |`-B`|`braceexpand`|The shell performs [brace expansion](../../syntax/expansion/brace.md) This is on by default.|
`-C` <BOOKMARK:tag_noclobber>`noclobber` Don't overwrite files on redirection operations. You can override that by specifying the `>|` redirection operator when needed. See [redirection](../../syntax/redirection.md) |`-C`|`noclobber`|Don't overwrite files on redirection operations. You can override that by specifying the `>|` redirection operator when needed. See [redirection](../../syntax/redirection.md)|
`-E` `errtrace` `ERR`-traps are inherited by by shell functions, command substitutions, and commands executed in a subshell environment. |`-E`|`errtrace`|`ERR`-traps are inherited by by shell functions, command substitutions, and commands executed in a subshell environment.|
`-H` `histexpand` Enable `!`-style history expansion. Defaults to `on` for interactive shells. |`-H`|`histexpand`|Enable `!`-style history expansion. Defaults to `on` for interactive shells.|
`-P` `physical` Don't follow symlinks when changing directories - use the physical filesystem structure. |`-P`|`physical`|Don't follow symlinks when changing directories - use the physical filesystem structure.|
`-T` `functrace` `DEBUG`- and `RETURN`-traps are inherited by subsequent environments, like `-E` for `ERR` trap. |`-T`|`functrace`|`DEBUG`- and `RETURN`-traps are inherited by subsequent environments, like `-E` for `ERR` trap.|
`-` \"End of options\" - all following arguments are assigned to the positional parameters, even when they begin with a dash. `-x` and `-v` options are turned off. Positional parameters are unchanged (unlike using `--`!) when no further arguments are given. |`-`||"End of options" - all following arguments are assigned to the positional parameters, even when they begin with a dash. `-x` and `-v` options are turned off. Positional parameters are unchanged (unlike using `--`!) when no further arguments are given.|
`--` If no arguments follow, the positional parameters are unset. With arguments, the positional parameters are set, even if the strings begin with a `-` (dash) like an option. |`--`||If no arguments follow, the positional parameters are unset. With arguments, the positional parameters are set, even if the strings begin with a `-` (dash) like an option.|
Long options usable with `-o` without a short equivalent |**Long options usable with `-o` without a short equivalent**|||
`emacs` Use an emacs-style command line editing interface. This is enabled by default when the shell is interactive, unless the shell is started with `--noediting` option. ||`emacs`|Use an emacs-style command line editing interface. This is enabled by default when the shell is interactive, unless the shell is started with `--noediting` option.|
`history` If set, command historization is done (enabled by default on interactive shells) ||`history`|If set, command historization is done (enabled by default on interactive shells)|
`ignoreeof` The effect is as if the shell command `IGNOREEOF=10` had been executed. See [shell variables](../../syntax/shellvars.md). ||`ignoreeof`|The effect is as if the shell command `IGNOREEOF=10` had been executed. See [shell variables](../../syntax/shellvars.md).|
`nolog` **(currently ignored)** ||`nolog`|**(currently ignored)**|
`pipefail` If set, the exit code from a pipeline is different from the normal (\"last command in pipeline\") behaviour: `TRUE` when no command failed, `FALSE` when something failed (code of the rightmost command that failed) ||`pipefail`|If set, the exit code from a pipeline is different from the normal ("last command in pipeline") behaviour: `TRUE` when no command failed, `FALSE` when something failed (code of the rightmost command that failed)|
`posix` When set, Bash runs in POSIX mode. ||`posix`|When set, Bash runs in POSIX mode.|
`vi` Enables a `vi`-style command line editing interface. ||`vi`|Enables a `vi`-style command line editing interface.|
## Examples ## Examples

View File

@ -6,7 +6,7 @@
## Description ## Description
The `shift` builtin command is used to \"shift\" the positional The `shift` builtin command is used to "shift" the positional
parameters by the given number `n` or by 1, if no number is given. parameters by the given number `n` or by 1, if no number is given.
This means, the number and the position of the positional parameters are This means, the number and the position of the positional parameters are
@ -15,18 +15,20 @@ becomes the first one, etc.
Imagine the following set of positional parameters (`$1` to `$4`): Imagine the following set of positional parameters (`$1` to `$4`):
1 This |Positional Parameter|Value|
--- ------ |-|-|
2 is |1|This
3 a |2|is|
4 test |3|a|
|4|test|
When you use `shift 1`, they will be changed to: When you use `shift 1`, they will be changed to:
1 is |Positional Parameter|Value|
--- ------ |-|-|
2 a |1|is|
3 test |2|a|
|3|test|
The [special parameter](../../syntax/shellvars.md#special_parameters) `$#` will The [special parameter](../../syntax/shellvars.md#special_parameters) `$#` will
reflect the final number of positional parameters. reflect the final number of positional parameters.
@ -40,12 +42,12 @@ There are no options.
### Return status ### Return status
Status Reason |Status|Reason|
-------- ----------------------------------------------------------------------------------------------------- |------|------|
0 no error |0|no error|
1 non-numeric argument |1|non-numeric argument|
1 given number (or the default 1) is bigger than the number of actually present positional parameters |1|given number (or the default 1) is bigger than the number of actually present positional parameters|
1 given number is negative |1|given number is negative|
## Examples ## Examples
@ -59,30 +61,37 @@ There are no options.
[shift_verbose](../../internals/shell_options.md#shift_verbose) [shift_verbose](../../internals/shell_options.md#shift_verbose)
[shopt](../../commands/builtin/shopt.md) option is enabled. Ksh93, pdksh, [shopt](../../commands/builtin/shopt.md) option is enabled. Ksh93, pdksh,
posh, mksh, and dash, all throw useless fatal shell posh, mksh, and dash, all throw useless fatal shell
errors.`$ dash -c 'f() { if shift; then echo "$1"; else echo "no args"; fi; }; f' errors.
```
$ dash -c 'f() { if shift; then echo "$1"; else echo "no args"; fi; }; f'
dash: 1: shift: can't shift that many dash: 1: shift: can't shift that many
` In most shells, you can work around this problem using the ```
In most shells, you can work around this problem using the
`command` builtin to suppress fatal `command` builtin to suppress fatal
errors caused by *special builtins*. <code> \$ dash -c \'f() { if errors caused by *special builtins*.
command shift 2>/dev/null; then echo \"\$1\"; else echo \"no ```
args\"; fi; }; f\' $ dash -c 'f() { if command shift 2>/dev/null; then echo "$1"; else echo "no args"; fi; }; f'
no args
no args </code> While, POSIX requires this behavior, it isn't very ```
While, POSIX requires this behavior, it isn't very
obvious and some shells don't do it correctly. To work around this, you obvious and some shells don't do it correctly. To work around this, you
can use something like: can use something like:
```
<code> \$ mksh -c \'f() { if ! \${1+false} && shift; then echo $ mksh -c 'f() { if ! ${1+false} && shift; then echo "$1"; else echo "no args"; fi; }; f'
\"\$1\"; else echo \"no args\"; fi; }; f\' no args </code> ~~The mksh no args
maintainer refuses to change either the `shift` or `command` builtins.~~ ```
<del>The mksh maintainer refuses to change either the `shift` or `command` builtins.</del>
[Fixed](https://github.com/MirBSD/mksh/commit/996e05548ab82f7ef2dea61f109cc7b6d13837fa). [Fixed](https://github.com/MirBSD/mksh/commit/996e05548ab82f7ef2dea61f109cc7b6d13837fa).
(Thanks!) (Thanks!)
- Perhaps almost as bad as the above, busybox sh's `shift` always - Perhaps almost as bad as the above, busybox sh's `shift` always
returns success, even when attempting to shift beyond the final returns success, even when attempting to shift beyond the final
argument. <code> \$ bb -c \'f() { if shift; then echo \"\$1\"; argument.
else echo \"no args\"; fi; }; f\' ```
$ bb -c 'f() { if shift; then echo "$1"; else echo "no args"; fi; }; f'
(no output) </code> The above mksh workaround will work in this case (no output)
```
The above mksh workaround will work in this case
too. too.
## See also ## See also

View File

@ -15,13 +15,13 @@ Note: Some of these options and other shell options can also be set with
### Options ### Options
Option Description |Option|Description|
-------- ----------------------------------------------------------------------------------------------------------------------------- |------|-----------|
`-o` Restrict the values of `<OPTNAME...>` to only those also known by [the set builtin](../../commands/builtin/set.md) |`-o`|Restrict the values of `<OPTNAME...>` to only those also known by [the set builtin](../../commands/builtin/set.md)|
`-p` Print all shell options and their current value. **Default**. |`-p`|Print all shell options and their current value. **Default**.|
`-q` Quiet mode. Set exit code if named option is set. For multiple options: `TRUE` if all options are set, `FALSE` otherwise |`-q`|Quiet mode. Set exit code if named option is set. For multiple options: `TRUE` if all options are set, `FALSE` otherwise|
`-s` Enable ([s]{.underline}et) the shell options named by `<OPTNAME...>` or list all *enabled* options if no names are given |`-s`|Enable (<u>s</u>et) the shell options named by `<OPTNAME...>` or list all *enabled* options if no names are given|
`-u` Disabe ([u]{.underline}nset) the shell options named by `<OPTNAME...>` or list all *disabled* options if no names are given |`-u`|Disabe (<u>u</u>nset) the shell options named by `<OPTNAME...>` or list all *disabled* options if no names are given|
As noted above, if only `-s` or `-u` are given without any option names, As noted above, if only `-s` or `-u` are given without any option names,
only the currently enabled (`-s`) or disabled (`-u`) options are only the currently enabled (`-s`) or disabled (`-u`) options are

View File

@ -6,8 +6,8 @@
## Description ## Description
The `trap` command is used to \"trap\" signals and other events. In this The `trap` command is used to "trap" signals and other events. In this
context, \"trapping\" means to install handler code. context, "trapping" means to install handler code.
The shell code `ARGUMENT` is to be read and executed whenever the shell The shell code `ARGUMENT` is to be read and executed whenever the shell
receives a signal or another event `SIGNAL`. The given `SIGNAL` receives a signal or another event `SIGNAL`. The given `SIGNAL`
@ -29,27 +29,27 @@ Special `ARGUMENT`s
Special events Special events
Name Code Description |Name|Code|Description|
---------- ------ -------------------------------------------------------------------------------------------------------------------------------------------- |----|----|-----------|
`EXIT` 0 executed on shell exit |`EXIT`|0|executed on shell exit|
`DEBUG` executed before every simple command |`DEBUG`||executed before every simple command|
`RETURN` executed when a shell function or a sourced code finishes executing |`RETURN`||executed when a shell function or a sourced code finishes executing|
`ERR` executed each time a command's failure would cause the shell to exit when the [`-e` option (`errexit`)](../../commands/builtin/set.md) is enabled |`ERR`||executed each time a command's failure would cause the shell to exit when the [`-e` option (`errexit`)](../../commands/builtin/set.md) is enabled|
### Options ### Options
Option Description |Option|Description|
-------- ------------------------------------------------------------------------------------------ |------|-----------|
`-l` print a list of signal names and their corresponding numbers |`-l`|print a list of signal names and their corresponding numbers|
`-p` display the trap commands associated with each signal specification in a reusable format |`-p`|display the trap commands associated with each signal specification in a reusable format|
### Return status ### Return status
Status Reason |Status|Reason|
-------- ------------------------------ |------|------|
0 no error/success |0|no error/success|
!=0 invalid option |!=0|invalid option|
!=0 invalid signal specification |!=0|invalid signal specification|
## Examples ## Examples

View File

@ -12,20 +12,20 @@ unset a variable first, then a function.
### Options ### Options
Option Description |Option|Description|
-------- -------------------------------------------------------------------------------------------------------------- |------|-----------|
`-f` treats each `NAME` as a function name |`-f`|treats each `NAME` as a function name|
`-v` treats each `NAME` as a variable name |`-v`|treats each `NAME` as a variable name|
`-n` treats each `NAME` as a name reference and unsets the variable itself rather than the variable it references |`-n`|treats each `NAME` as a name reference and unsets the variable itself rather than the variable it references|
### Exit status ### Exit status
Status Reason |Status|Reason|
-------- ---------------------------------------------------- |------|------|
0 no error |0|no error|
!=0 invalid option |!=0|invalid option|
!=0 invalid combination of options (`-v` **and** `-f`) |!=0|invalid combination of options (`-v` **and** `-f`)|
!=0 a given `NAME` is read-only |!=0|a given `NAME` is read-only|
## Examples ## Examples
@ -71,8 +71,8 @@ Here's a demonstration of this behavior.
local -a 'fnames=("${FUNCNAME[@]:1}")' local -a 'fnames=("${FUNCNAME[@]:1}")'
fi fi
if (( ! ${#fnames[@]} )); then if (( ! ${#fnames[@]} )); then
printf 0 printf 0
return return
fi fi
@ -123,7 +123,7 @@ Some things to observe:
- `unset2` is only really needed once. We remain 5 levels deep in - `unset2` is only really needed once. We remain 5 levels deep in
`f`'s for the remaining `unset` calls, which peel away the outer `f`'s for the remaining `unset` calls, which peel away the outer
layers of `a`'s. layers of `a`'s.
- Notice that the \"a\" is unset using an ordinary unset command at - Notice that the "a" is unset using an ordinary unset command at
recursion depth 1, and subsequently calling unset reveals a again in recursion depth 1, and subsequently calling unset reveals a again in
the global scope, which has since been modified in a lower scope the global scope, which has since been modified in a lower scope
using declare -g. using declare -g.
@ -133,7 +133,7 @@ Some things to observe:
- This doesn't apply to individual array elements. If two local - This doesn't apply to individual array elements. If two local
arrays of the same name appear in different scopes, the entire array arrays of the same name appear in different scopes, the entire array
of the inner scope needs to be unset before any elements of the of the inner scope needs to be unset before any elements of the
outer array become visible. This makes \"unset\" and \"unset2\" outer array become visible. This makes "unset" and "unset2"
identical for individual array elements, and for arrays as a whole, identical for individual array elements, and for arrays as a whole,
unset and unset2 behave as they do for scalar variables. unset and unset2 behave as they do for scalar variables.

View File

@ -14,7 +14,7 @@ exit status.
- waits for a specific job (asynchronous command) and report its exit - waits for a specific job (asynchronous command) and report its exit
status if one or more `ID` is given status if one or more `ID` is given
- waits for all running jobs (asynchronous commands) - waits for all running jobs (asynchronous commands)
- waits for \"the next\" job (`-n` option) - waits for "the next" job (`-n` option)
- waits for termination instead of status change (`-f` option) - waits for termination instead of status change (`-f` option)
`ID` may be an operating system process identifier or a shell job `ID` may be an operating system process identifier or a shell job
@ -22,20 +22,20 @@ specification.
### Options ### Options
Option Description |Option|Description|
-------------- --------------------------------------------------------------------------------------------------------------------------------- |------|-----------|
`-n` Waits for \"the next\" child to exit (as opposed to \"all children\" without this option). Accepts a list of IDs (jobs) |`-n`|Waits for "the next" child to exit (as opposed to "all children" without this option). Accepts a list of IDs (jobs)|
`-f` Waits for the termination of the given `ID` (instead of waiting for a status change only) |`-f`|Waits for the termination of the given `ID` (instead of waiting for a status change only)|
`-p VARNAME` When waiting for a list (-n) or all jobs, writes the job ID to the job that was actually terminated into the variable `VARNAME` |`-p VARNAME`|When waiting for a list (-n) or all jobs, writes the job ID to the job that was actually terminated into the variable `VARNAME`|
### Return status ### Return status
The return status is the return status of the job waited for, or The return status is the return status of the job waited for, or
Status Reason |Status|Reason|
-------- ------------------------------------------------- |------|------|
0 waited for all jobs in shell's job list |0|waited for all jobs in shell's job list|
1 the given `ID` is not a valid job or process ID |1|the given `ID` is not a valid job or process ID|
## Examples ## Examples

View File

@ -1,7 +1,7 @@
# Parameter # Parameter
Also the article for: [variable]{.underline}, [positional Also the article for: <u>variable</u>, <u>positional
parameter]{.underline}, [special parameter]{.underline} parameter</u>, <u>special parameter</u>
In Bash, a parameter is simply an entity that stores values and can be In Bash, a parameter is simply an entity that stores values and can be
referenced. Depending on the type, the parameters can be set directly, referenced. Depending on the type, the parameters can be set directly,

View File

@ -10,7 +10,8 @@ This behaviour alone doesn't help much. A shell knits some intelligence
and flow control around the possibility to execute commands - it's a and flow control around the possibility to execute commands - it's a
complete commandline-oriented user-interface (UI). complete commandline-oriented user-interface (UI).
FIXME !!! warning "FIXME"
tbd.
## See also ## See also

View File

@ -12,9 +12,9 @@ tags:
## Introduction ## Introduction
dc(1) is a non standard, but commonly found, reverse-polish Desk dc(1) is a non standard, but commonly found, reverse-polish Desk
Calculator. According to Ken Thompson, \"dc is the oldest language on Calculator. According to Ken Thompson, "dc is the oldest language on
Unix; it was written on the PDP-7 and ported to the PDP-11 before Unix Unix; it was written on the PDP-7 and ported to the PDP-11 before Unix
\[itself\] was ported\". \[itself\] was ported".
Historically the standard bc(1) has been implemented as a *front-end to Historically the standard bc(1) has been implemented as a *front-end to
dc*. dc*.
@ -26,15 +26,15 @@ stack first, then an operation is applied to them. Instead of writing
`1+1`, you write `1 1+`. `1+1`, you write `1 1+`.
By default `dc`, unlike `bc`, doesn't print anything, the result is By default `dc`, unlike `bc`, doesn't print anything, the result is
pushed on the stack. You have to use the \"p\" command to print the pushed on the stack. You have to use the "p" command to print the
element at the top of the stack. Thus a simple operation looks like: element at the top of the stack. Thus a simple operation looks like:
$ dc <<< '1 1+pq' $ dc <<< '1 1+pq'
2 2
I used a \"here string\" present in bash 3.x, ksh93 and zsh. if your I used a "here string" present in bash 3.x, ksh93 and zsh. if your
shell doesn't support this, you can use `echo '1 1+p' | dc` or if you shell doesn't support this, you can use `echo '1 1+p' | dc` or if you
have GNU `dc`, you can use `dc -e '1 1 +p`\'. have GNU `dc`, you can use `dc -e '1 1 +p'`.
Of course, you can also just run `dc` and enter the commands. Of course, you can also just run `dc` and enter the commands.
@ -53,7 +53,7 @@ GNU `dc` adds a couple more.
To input a negative number you need to use the `_` (underscore) To input a negative number you need to use the `_` (underscore)
character: character:
$ dc <<< '1_1-p' $ dc <<< '1_1-p'
2 2
You can use the *digits* `0` to `9` and the *letters* `A` to `F` as You can use the *digits* `0` to `9` and the *letters* `A` to `F` as
@ -63,21 +63,21 @@ with lower case characters. A number with a letter is considered
hexadecimal: hexadecimal:
dc <<< 'Ap' dc <<< 'Ap'
10 10
The **output** is converted to **base 10** by default The **output** is converted to **base 10** by default
## Scale And Base ## Scale And Base
`dc` is a calulator with abitrary precision, by default this precision `dc` is a calulator with abitrary precision, by default this precision
is 0. thus `dc <<< "5 4/p"` prints \"1\". is 0. thus `dc <<< "5 4/p"` prints "1".
We can increase the precision using the `k` command. It pops the value We can increase the precision using the `k` command. It pops the value
at the top of the stack and uses it as the precision argument: at the top of the stack and uses it as the precision argument:
dc <<< '2k5 4/p' # prints 1.25 dc <<< '2k5 4/p' # prints 1.25
dc <<< '4k5 4/p' # prints 1.2500 dc <<< '4k5 4/p' # prints 1.2500
dc <<< '100k 2vp' dc <<< '100k 2vp'
1.4142135623730950488016887242096980785696718753769480731766797379907\ 1.4142135623730950488016887242096980785696718753769480731766797379907\
324784621070388503875343276415727 324784621070388503875343276415727
@ -102,7 +102,7 @@ commands, including `i`:
16i 16o # base is 16 for input and output 16i 16o # base is 16 for input and output
10p # prints 10 10p # prints 10
10i # ! set the base to 10 i.e. to 16 decimal 10i # ! set the base to 10 i.e. to 16 decimal
17p # prints 17 17p # prints 17
EOF EOF
This code prints 17 while we might think that `10i` reverts the base This code prints 17 while we might think that `10i` reverts the base
@ -123,9 +123,6 @@ There are two basic commands to manipulate the stack:
- `d` duplicates the top of the stack - `d` duplicates the top of the stack
- `c` clears the stack - `c` clears the stack
```{=html}
<!-- -->
```
$ dc << EOF $ dc << EOF
2 # put 2 on the stack 2 # put 2 on the stack
d # duplicate i.e. put another 2 on the stack d # duplicate i.e. put another 2 on the stack
@ -228,7 +225,7 @@ we are used to reading:
EOF EOF
Some `dc` have `>R <R =R`, GNU `dc` had some more, check your manual. Some `dc` have `>R <R =R`, GNU `dc` had some more, check your manual.
Note that the test \"consumes\" its operands: the 2 first elements are Note that the test "consumes" its operands: the 2 first elements are
popped off the stack (you can verify that popped off the stack (you can verify that
`dc <<< "[f]sR 2 1 >R 1 2 >R f"` doesn't print anything) `dc <<< "[f]sR 2 1 >R 1 2 >R f"` doesn't print anything)
@ -246,13 +243,13 @@ as `dc` relies on a stack we can, in fact, use the macro recursively
We have recursivity, we have test, we have loops: We have recursivity, we have test, we have loops:
dc << EOF dc << EOF
[ li # put our index i on the stack [ li # put our index i on the stack
p # print it, to see what's going on p # print it, to see what's going on
1 - # we decrement the index by one 1 - # we decrement the index by one
si # store decremented index (i=i-1) si # store decremented index (i=i-1)
0 li >L # if i > 0 then execute L 0 li >L # if i > 0 then execute L
] sL # store our macro with the name L ] sL # store our macro with the name L
10 si # let's give to our index the value 10 10 si # let's give to our index the value 10
lLx # and start our loop lLx # and start our loop
EOF EOF
@ -260,16 +257,16 @@ We have recursivity, we have test, we have loops:
Of course code written this way is far too easy to read! Make sure to Of course code written this way is far too easy to read! Make sure to
remove all those extra spaces newlines and comments: remove all those extra spaces newlines and comments:
dc <<< '[lip1-si0li>L]sL10silLx' dc <<< '[lip1-si0li>L]sL10silLx'
dc <<< '[p1-d0<L]sL10lLx' # use the stack instead of a register dc <<< '[p1-d0<L]sL10lLx' # use the stack instead of a register
I\'ll let you figure out the second example, it's not hard, it uses the I'll let you figure out the second example, it's not hard, it uses the
stack instead of a register for the index. stack instead of a register for the index.
## Next ## Next
Check your dc manual, i haven't decribed everything, like arrays (only Check your dc manual, i haven't decribed everything, like arrays (only
documented with \"; : are used by bc(1) for array operations\" on documented with "; : are used by bc(1) for array operations" on
solaris, probably because *echo \'1 0:a 0Sa 2 0:a La 0;ap\' \| dc* solaris, probably because *echo \'1 0:a 0Sa 2 0:a La 0;ap\' \| dc*
results in //Segmentation Fault (core dump) //, the latest solaris uses results in //Segmentation Fault (core dump) //, the latest solaris uses
GNU dc) GNU dc)

View File

@ -10,7 +10,7 @@ tags:
# Collapsing Functions # Collapsing Functions
## What is a \"Collapsing Function\"? ## What is a "Collapsing Function"?
A collapsing function is a function whose behavior changes depending A collapsing function is a function whose behavior changes depending
upon the circumstances under which it's run. Function collapsing is upon the circumstances under which it's run. Function collapsing is
@ -21,7 +21,7 @@ never changes.
Function collapsing requires some static feature in the environment. A Function collapsing requires some static feature in the environment. A
common example is a script that gives the user the option of having common example is a script that gives the user the option of having
\"verbose\" output. "verbose" output.
#!/bin/bash #!/bin/bash
@ -49,58 +49,63 @@ common example is a script that gives the user the option of having
## How does it work? ## How does it work?
The first time you run chatter(), the function redefines itself based on The first time you run chatter(), the function redefines itself based on
the value of verbose. Thereafter, chatter doesn't check \$verbose, it the value of verbose. Thereafter, chatter doesn't check `$verbose`, it
simply is. Further calls to the function reflect its collapsed nature. simply is. Further calls to the function reflect its collapsed nature.
If verbose is unset, chatter will echo nothing, with no extra effort If verbose is unset, chatter will echo nothing, with no extra effort
from the developer. from the developer.
## More examples ## More examples
FIXME Add more examples! !!! warning "FIXME"
Add more examples!
# Somewhat more portable find -executable ```bash
# FIXME/UNTESTED (I don't have access to all of the different versions of find.) # Somewhat more portable find -executable
# Usage: find PATH ARGS -- use find like normal, except use -executable instead of # FIXME/UNTESTED (I don't have access to all of the different versions of find.)
# various versions of -perm /+ blah blah and hacks # Usage: find PATH ARGS -- use find like normal, except use -executable instead of
# various versions of -perm /+ blah blah and hacks
find() {
hash find || { echo 'find not found!'; exit 1; }
# We can be pretty sure "$0" should be executable.
if [[ $(command find "$0" -executable 2> /dev/null) ]]; then
unset -f find # We can just use the command find
elif [[ $(command find "$0" -perm /u+x 2> /dev/null) ]]; then
find() { find() {
hash find || { echo 'find not found!'; exit 1; } typeset arg args
# We can be pretty sure "$0" should be executable. for arg do
if [[ $(command find "$0" -executable 2> /dev/null) ]]; then [[ $arg = -executable ]] && args+=(-perm /u+x) || args+=("$arg")
unset -f find # We can just use the command find done
elif [[ $(command find "$0" -perm /u+x 2> /dev/null) ]]; then command find "${args[@]}"
find() {
typeset arg args
for arg do
[[ $arg = -executable ]] && args+=(-perm /u+x) || args+=("$arg")
done
command find "${args[@]}"
}
elif [[ $(command find "$0" -perm +u+x 2> /dev/null) ]]; then
find() {
typeset arg args
for arg do
[[ $arg = -executable ]] && args+=(-perm +u+x) || args+=("$arg")
done
command find "${args[@]}"
}
else # Last resort
find() {
typeset arg args
for arg do
[[ $arg = -executable ]] && args+=(-exec test -x {} \; -print) || args+=("$arg")
done
command find "${args[@]}"
}
fi
find "$@"
} }
elif [[ $(command find "$0" -perm +u+x 2> /dev/null) ]]; then
find() {
typeset arg args
for arg do
[[ $arg = -executable ]] && args+=(-perm +u+x) || args+=("$arg")
done
command find "${args[@]}"
}
else # Last resort
find() {
typeset arg args
for arg do
[[ $arg = -executable ]] && args+=(-exec test -x {} \; -print) || args+=("$arg")
done
command find "${args[@]}"
}
fi
find "$@"
}
```
#!/bin/bash ```bash
# Using collapsing functions to turn debug messages on/off #!/bin/bash
# Using collapsing functions to turn debug messages on/off
[ "--debug" = "$1" ] && dbg=echo || dbg=: [ "--debug" = "$1" ] && dbg=echo || dbg=:
# From now on if you use $dbg instead of echo, you can select if messages will be shown # From now on if you use $dbg instead of echo, you can select if messages will be shown
$dbg "This message will only be displayed if --debug is specified at the command line $dbg "This message will only be displayed if --debug is specified at the command line
```

View File

@ -16,7 +16,7 @@ tags:
For this task, you don't have to write large parser routines (unless For this task, you don't have to write large parser routines (unless
you want it 100% secure or you want a special file syntax) - you can use you want it 100% secure or you want a special file syntax) - you can use
the Bash source command. The file to be sourced should be formated in the Bash source command. The file to be sourced should be formated in
key=\"value\" format, otherwise bash will try to interpret commands: key="value" format, otherwise bash will try to interpret commands:
#!/bin/bash #!/bin/bash
echo "Reading config...." >&2 echo "Reading config...." >&2
@ -50,7 +50,7 @@ usage of the dot is identical:
## Per-user configs ## Per-user configs
There's also a way to provide a system-wide config file in /etc and a There's also a way to provide a system-wide config file in /etc and a
custom config in \~/(user's home) to override system-wide defaults. In custom config in ~/(user's home) to override system-wide defaults. In
the following example, the if/then construct is used to check for the the following example, the if/then construct is used to check for the
existance of a user-specific config: existance of a user-specific config:
@ -66,11 +66,11 @@ existance of a user-specific config:
As mentioned earlier, the sourced file can contain anything a Bash As mentioned earlier, the sourced file can contain anything a Bash
script can. Essentially, it **is** an included Bash script. That creates script can. Essentially, it **is** an included Bash script. That creates
security issues. A malicicios person can \"execute\" arbitrary code when security issues. A malicicios person can "execute" arbitrary code when
your script is sourcing its config file. You might want to allow only your script is sourcing its config file. You might want to allow only
constructs in the form `NAME=VALUE` in that file (variable assignment constructs in the form `NAME=VALUE` in that file (variable assignment
syntax) and maybe comments (though technically, comments are syntax) and maybe comments (though technically, comments are
unimportant). Imagine the following \"config file\", containing some unimportant). Imagine the following "config file", containing some
malicious code: malicious code:
# cool config file for my even cooler script # cool config file for my even cooler script
@ -107,7 +107,7 @@ filters by description:
# now source it, either the original or the filtered variant # now source it, either the original or the filtered variant
source "$configfile" source "$configfile"
**[To make clear what it does:]{.underline}** egrep checks if the file <u>**To make clear what it does:**</u> egrep checks if the file
contains something we don't want, if yes, egrep filters the file and contains something we don't want, if yes, egrep filters the file and
writes the filtered contents to a new file. If done, the original file writes the filtered contents to a new file. If done, the original file
name is changed to the name stored in the variable `configfile`. The name is changed to the name stored in the variable `configfile`. The

View File

@ -1,36 +1,36 @@
# Dissect a bad oneliner # Dissect a bad oneliner
``` bash ```bash
$ ls *.zip | while read i; do j=`echo $i | sed 's/.zip//g'`; mkdir $j; cd $j; unzip ../$i; cd ..; done $ ls *.zip | while read i; do j=`echo $i | sed 's/.zip//g'`; mkdir $j; cd $j; unzip ../$i; cd ..; done
``` ```
This is an actual one-liner someone asked about in `#bash`. **There are This is an actual one-liner someone asked about in `#bash`. **There are
several things wrong with it. Let's break it down!** several things wrong with it. Let's break it down!**
``` bash ```bash
$ ls *.zip | while read i; do ...; done $ ls *.zip | while read i; do ...; done
``` ```
(Please read <http://mywiki.wooledge.org/ParsingLs>.) This command (Please read <http://mywiki.wooledge.org/ParsingLs>.) This command
executes `ls` on the expansion of `*.zip`. Assuming there are filenames executes `ls` on the expansion of `*.zip`. Assuming there are filenames
in the current directory that end in \'.zip\', ls will give a in the current directory that end in '.zip', ls will give a
human-readable list of those names. The output of ls is not for parsing. human-readable list of those names. The output of ls is not for parsing.
But in sh and bash alike, we can loop safely over the glob itself: But in sh and bash alike, we can loop safely over the glob itself:
``` bash ```bash
$ for i in *.zip; do j=`echo $i | sed 's/.zip//g'`; mkdir $j; cd $j; unzip ../$i; cd ..; done $ for i in *.zip; do j=`echo $i | sed 's/.zip//g'`; mkdir $j; cd $j; unzip ../$i; cd ..; done
``` ```
Let's break it down some more! Let's break it down some more!
``` bash ```bash
j=`echo $i | sed 's/.zip//g'` # where $i is some name ending in '.zip' j=`echo $i | sed 's/.zip//g'` # where $i is some name ending in '.zip'
``` ```
The goal here seems to be get the filename without its `.zip` extension. The goal here seems to be get the filename without its `.zip` extension.
In fact, there is a POSIX(r)-compliant command to do this: `basename` In fact, there is a POSIX(r)-compliant command to do this: `basename`
The implementation here is suboptimal in several ways, but the only The implementation here is suboptimal in several ways, but the only
thing that's genuinely error-prone with this is \"`echo $i`\". Echoing thing that's genuinely error-prone with this is "`echo $i`". Echoing
an *unquoted* variable means an *unquoted* variable means
[wordsplitting](../syntax/expansion/wordsplit.md) will take place, so any [wordsplitting](../syntax/expansion/wordsplit.md) will take place, so any
whitespace in `$i` will essentially be normalized. In `sh` it is whitespace in `$i` will essentially be normalized. In `sh` it is
@ -41,7 +41,7 @@ performance in a loop). Just for good measure, let's use the more
readable, [modern](../syntax/expansion/cmdsubst.md) `$()` construct instead readable, [modern](../syntax/expansion/cmdsubst.md) `$()` construct instead
of the old style backticks: of the old style backticks:
``` bash ```bash
sh $ for i in *.zip; do j=$(basename "$i" ".zip"); mkdir $j; cd $j; unzip ../$i; cd ..; done sh $ for i in *.zip; do j=$(basename "$i" ".zip"); mkdir $j; cd $j; unzip ../$i; cd ..; done
``` ```
@ -49,27 +49,27 @@ In Bash we don't need the subshell or the external basename command.
See [Substring removal with parameter See [Substring removal with parameter
expansion](../syntax/pe.md#substring_removal): expansion](../syntax/pe.md#substring_removal):
``` bash ```bash
bash $ for i in *.zip; do j="${i%.zip}"; mkdir $j; cd $j; unzip ../$i; cd ..; done bash $ for i in *.zip; do j="${i%.zip}"; mkdir $j; cd $j; unzip ../$i; cd ..; done
``` ```
Let's keep going: Let's keep going:
``` bash ```bash
$ mkdir $j; cd $j; ...; cd .. $ mkdir $j; cd $j; ...; cd ..
``` ```
As a programmer, you **never** know the situation under which your As a programmer, you **never** know the situation under which your
program will run. Even if you do, the following best practice will never program will run. Even if you do, the following best practice will never
hurt: When a following command depends on the success of a previous hurt: When a following command depends on the success of a previous
command(s), check for success! You can do this with the \"`&&`\" command(s), check for success! You can do this with the "`&&`"
conjunction, that way, if the previous command fails, bash will not try conjunction, that way, if the previous command fails, bash will not try
to execute the following command(s). It's fully POSIX(r). Oh, and to execute the following command(s). It's fully POSIX(r). Oh, and
remember what I said about [wordsplitting](../syntax/expansion/wordsplit.md) remember what I said about [wordsplitting](../syntax/expansion/wordsplit.md)
in the previous step? Well, if you don't quote `$j`, wordsplitting can in the previous step? Well, if you don't quote `$j`, wordsplitting can
happen again. happen again.
``` bash ```bash
$ mkdir "$j" && cd "$j" && ... && cd .. $ mkdir "$j" && cd "$j" && ... && cd ..
``` ```
@ -78,47 +78,47 @@ contains a slash? Then `cd ..` will not return to the original
directory. That's wrong! `cd -` causes cd to return to the previous directory. That's wrong! `cd -` causes cd to return to the previous
working directory, so it's a much better choice: working directory, so it's a much better choice:
``` bash ```bash
$ mkdir "$j" && cd "$j" && ... && cd - $ mkdir "$j" && cd "$j" && ... && cd -
``` ```
(If it occurred to you that I forgot to check for success after cd -, (If it occurred to you that I forgot to check for success after cd -,
good job! You could do this with `{ cd - || break; }`, but I\'m going to good job! You could do this with `{ cd - || break; }`, but I'm going to
leave that out because it's verbose and I think it's likely that we leave that out because it's verbose and I think it's likely that we
will be able to get back to our original working directory without a will be able to get back to our original working directory without a
problem.) problem.)
So now we have: So now we have:
``` bash ```bash
sh $ for i in *.zip; do j=$(basename "$i" ".zip"); mkdir "$j" && cd "$j" && unzip ../$i && cd -; done sh $ for i in *.zip; do j=$(basename "$i" ".zip"); mkdir "$j" && cd "$j" && unzip ../$i && cd -; done
``` ```
``` bash ```bash
bash $ for i in *.zip; do j="${i%.zip}"; mkdir "$j" && cd "$j" && unzip ../$i && cd -; done bash $ for i in *.zip; do j="${i%.zip}"; mkdir "$j" && cd "$j" && unzip ../$i && cd -; done
``` ```
Let's throw the `unzip` command back in the mix: Let's throw the `unzip` command back in the mix:
``` bash ```bash
mkdir "$j" && cd "$j" && unzip ../$i && cd - mkdir "$j" && cd "$j" && unzip ../$i && cd -
``` ```
Well, besides word splitting, there's nothing terribly wrong with this. Well, besides word splitting, there's nothing terribly wrong with this.
Still, did it occur to you that unzip might already be able to target a Still, did it occur to you that unzip might already be able to target a
directory? There isn't a standard for the `unzip` command, but all the directory? There isn't a standard for the `unzip` command, but all the
implementations I\'ve seen can do it with the -d flag. So we can drop implementations I've seen can do it with the -d flag. So we can drop
the cd commands entirely: the cd commands entirely:
``` bash ```bash
$ mkdir "$j" && unzip -d "$j" "$i" $ mkdir "$j" && unzip -d "$j" "$i"
``` ```
``` bash ```bash
sh $ for i in *.zip; do j=$(basename "$i" ".zip"); mkdir "$j" && unzip -d "$j" "$i"; done sh $ for i in *.zip; do j=$(basename "$i" ".zip"); mkdir "$j" && unzip -d "$j" "$i"; done
``` ```
``` bash ```bash
bash $ for i in *.zip; do j="${i%.zip}"; mkdir "$j" && unzip -d "$j" "$i"; done bash $ for i in *.zip; do j="${i%.zip}"; mkdir "$j" && unzip -d "$j" "$i"; done
``` ```

View File

@ -20,7 +20,7 @@ contents with `sed`, and the file is open elsewhere and read by some
process, you will find out that GNU `sed` and its `-i` option will not process, you will find out that GNU `sed` and its `-i` option will not
allow you to edit the file. There are circumstances where you may need allow you to edit the file. There are circumstances where you may need
that, e.g. editing active and open files, the lack of GNU, or other that, e.g. editing active and open files, the lack of GNU, or other
`sed`, with \"in-place\" option available. `sed`, with "in-place" option available.
Why `ed`? Why `ed`?
@ -40,12 +40,12 @@ Since `ed` is an interactive text editor, it reads and executes commands
that come from `stdin`. There are several ways to feed our commands to that come from `stdin`. There are several ways to feed our commands to
ed: ed:
**[Pipelines]{.underline}** **<u>Pipelines</u>**
echo '<ED-COMMANDS>' | ed <FILE> echo '<ED-COMMANDS>' | ed <FILE>
To inject the needed newlines, etc. it may be easier to use the builtin To inject the needed newlines, etc. it may be easier to use the builtin
command, `printf` (\"help printf\"). Shown here as an example Bash command, `printf` ("help printf"). Shown here as an example Bash
function to prefix text to file content: function to prefix text to file content:
@ -55,11 +55,11 @@ function to prefix text to file content:
printf '%s\n' H 1i "$1" . w | ed -s "$2" printf '%s\n' H 1i "$1" . w | ed -s "$2"
} }
**[Here-strings]{.underline}** **<u>Here-strings</u>**
ed <FILE> <<< '<ED-COMMANDS>' ed <FILE> <<< '<ED-COMMANDS>'
**[Here-documents]{.underline}** **<u>Here-documents</u>**
ed <FILE> <<EOF ed <FILE> <<EOF
<ED-COMMANDS> <ED-COMMANDS>
@ -71,17 +71,17 @@ it looks best here IMHO.
There are other ways to provide input to `ed`. For example, process There are other ways to provide input to `ed`. For example, process
substitution. But these should be enough for daily needs. substitution. But these should be enough for daily needs.
Since `ed` wants commands separated by newlines, I\'ll use a special Since `ed` wants commands separated by newlines, I'll use a special
Bash quoting method, the C-like strings `$'TEXT'`, as it can interpret a Bash quoting method, the C-like strings `$'TEXT'`, as it can interpret a
set of various escape sequences and special characters. I\'ll use the set of various escape sequences and special characters. I'll use the
`-s` option to make it less verbose. `-s` option to make it less verbose.
## The basic interface ## The basic interface
Check the `ed` manpage for details Check the `ed` manpage for details
Similar to `vi` or `vim`, `ed` has a \"command mode\" and an Similar to `vi` or `vim`, `ed` has a "command mode" and an
\"interactive mode\". For non-interactive use, the command mode is the "interactive mode". For non-interactive use, the command mode is the
usual choice. usual choice.
Commands to `ed` have a simple and regular structure: zero, one, or two Commands to `ed` have a simple and regular structure: zero, one, or two
@ -103,7 +103,7 @@ no RE can ever match a newline.
## Debugging your ed scripts ## Debugging your ed scripts
By default, `ed` is not very talkative and will simply print a \"?\" By default, `ed` is not very talkative and will simply print a "?"
when an error occurs. Interactively you can use the `h` command to get a when an error occurs. Interactively you can use the `h` command to get a
short message explaining the last error. You can also turn on a mode short message explaining the last error. You can also turn on a mode
that makes `ed` automatically print this message with the `H` command. that makes `ed` automatically print this message with the `H` command.
@ -156,8 +156,8 @@ lines, it's considered an error.**
ed -s test.txt <<< $',s/Windows(R)-compatible/POSIX-conform/g\nw' ed -s test.txt <<< $',s/Windows(R)-compatible/POSIX-conform/g\nw'
[Note:]{.underline} The comma as single address operator is an alias for <u>Note:</u> The comma as single address operator is an alias for
`1,$` (\"all lines\"). `1,$` ("all lines").
#### Substitutions in specific lines #### Substitutions in specific lines
@ -188,7 +188,7 @@ regexp
#### Move a block of text #### Move a block of text
\...using the `m` command: `<ADDRESS> m <TARGET-ADDRESS>` ...using the `m` command: `<ADDRESS> m <TARGET-ADDRESS>`
This is definitely something that can't be done easily with sed. This is definitely something that can't be done easily with sed.
@ -200,7 +200,7 @@ This is definitely something that can't be done easily with sed.
#### Copy a block of text #### Copy a block of text
\...using the `t` command: `<ADDRESS> t <TARGET-ADDRESS>` ...using the `t` command: `<ADDRESS> t <TARGET-ADDRESS>`
You use the `t` command just like you use the `m` (move) command. You use the `t` command just like you use the `m` (move) command.
@ -212,7 +212,7 @@ You use the `t` command just like you use the `m` (move) command.
#### Join all lines #### Join all lines
\...but leave the final newline intact. This is done by an extra ...but leave the final newline intact. This is done by an extra
command: `j` (join). command: `j` (join).
ed -s file <<< $'1,$j\nw' ed -s file <<< $'1,$j\nw'
@ -263,7 +263,7 @@ about it with the g (global) command:
echo $'1\n1\n3' > file echo $'1\n1\n3' > file
#replace all lines matching 1 by "replacement" #replace all lines matching 1 by "replacement"
ed -s file <<< $'g/1/s/1/replacement/\n,p' ed -s file <<< $'g/1/s/1/replacement/\n,p'
#replace the first line matching 1 by "replacement" #replace the first line matching 1 by "replacement"
#(because it starts searching from the last line) #(because it starts searching from the last line)
@ -272,7 +272,7 @@ about it with the g (global) command:
**\_\_ an error stops the script \_\_** **\_\_ an error stops the script \_\_**
You might think that it's not a problem and that the same thing happens You might think that it's not a problem and that the same thing happens
with sed and you\'re right, with the exception that if ed does not find with sed and you're right, with the exception that if ed does not find
a pattern it's an error, while sed just continues with the next line. a pattern it's an error, while sed just continues with the next line.
For instance, let's say that you want to change foo to bar on the first For instance, let's say that you want to change foo to bar on the first
line of the file and add something after the next line, ed will stop if line of the file and add something after the next line, ed will stop if
@ -299,9 +299,9 @@ attempt the substitution on all non blank lines
**\_\_ shell parameters are expanded \_\_** **\_\_ shell parameters are expanded \_\_**
If you don't quote the delimiter, \$ has a special meaning. This sounds If you don't quote the delimiter, `$` has a special meaning. This sounds
obvious but it's easy to forget this fact when you use addresses like obvious but it's easy to forget this fact when you use addresses like
\$-1 or commands like \$a. Either quote the \$ or the delimiter: `$-1` or commands like `$a`. Either quote the `$` or the delimiter:
#fails #fails
ed -s file << EOF ed -s file << EOF
@ -309,15 +309,15 @@ obvious but it's easy to forget this fact when you use addresses like
last line last line
. .
w w
EOF EOF
#ok #ok
ed -s file << EOF ed -s file << EOF
\$a $a
last line last line
. .
w w
EOF EOF
#ok again #ok again
ed -s file << 'EOF' ed -s file << 'EOF'
@ -325,11 +325,11 @@ obvious but it's easy to forget this fact when you use addresses like
last line last line
. .
w w
EOF EOF
**\_\_ \".\" is not a command \_\_** **\_\_ "." is not a command \_\_**
The . used to terminate the command \"a\" must be the only thing on the The . used to terminate the command "a" must be the only thing on the
line. take care if you indent the commands: line. take care if you indent the commands:
#ed doesn't care about the spaces before the commands, but the . must be the only thing on the line: #ed doesn't care about the spaces before the commands, but the . must be the only thing on the line:
@ -358,7 +358,7 @@ expression => print). ref
### wc -l ### wc -l
Since the default for the `ed` \"print line number\" command is the last Since the default for the `ed` "print line number" command is the last
line, a simple `=` (equal sign) will print this line number and thus the line, a simple `=` (equal sign) will print this line number and thus the
number of lines of the file: number of lines of the file:
@ -366,23 +366,24 @@ number of lines of the file:
### cat ### cat
Yea, it's a joke\... Yea, it's a joke...
ed -s file <<< $',p' ed -s file <<< $',p'
\...but a similar thing to `cat` showing line-endings and escapes can be ...but a similar thing to `cat` showing line-endings and escapes can be
done with the `list` command (l): done with the `list` command (l):
ed -s file <<< $',l' ed -s file <<< $',l'
FIXME to be continued !!! warning "FIXME"
to be continued
## Links ## Links
Reference: Reference:
- [Gnu ed](http://www.gnu.org/software/ed/manual/ed_manual.html) - if - [Gnu ed](http://www.gnu.org/software/ed/manual/ed_manual.html) - if
we had to guess, you\'re probably using this one. we had to guess, you're probably using this one.
- POSIX - POSIX
[ed](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ed.html#tag_20_38), [ed](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ed.html#tag_20_38),
[ex](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ex.html#tag_20_40), [ex](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ex.html#tag_20_40),

View File

@ -27,7 +27,7 @@ are:
- Being a builtin, `getopts` can set shell variables to use for - Being a builtin, `getopts` can set shell variables to use for
parsing (impossible for an *external* process!) parsing (impossible for an *external* process!)
- There's no need to argue with several `getopt` implementations - There's no need to argue with several `getopt` implementations
which had buggy concepts in the past (whitespace, \...) which had buggy concepts in the past (whitespace, ...)
- `getopts` is defined in POSIX(r). - `getopts` is defined in POSIX(r).
------------------------------------------------------------------------ ------------------------------------------------------------------------
@ -38,7 +38,7 @@ parameters](../scripting/posparams.md).
### Terminology ### Terminology
It's useful to know what we\'re talking about here, so let's see\... It's useful to know what we're talking about here, so let's see...
Consider the following command line: Consider the following command line:
mybackup -x -f /etc/mybackup.conf -r ./foo.txt ./bar.txt mybackup -x -f /etc/mybackup.conf -r ./foo.txt ./bar.txt
@ -97,13 +97,13 @@ which means [end of options](../dict/end_of_options.md).
### Used variables ### Used variables
variable description |variable|description|
------------------------------------ --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |--------|-----------|
[OPTIND](../syntax/shellvars.md#OPTIND) Holds the index to the next argument to be processed. This is how `getopts` \"remembers\" its own status between invocations. Also useful to shift the positional parameters after processing with `getopts`. `OPTIND` is initially set to 1, and **needs to be re-set to 1 if you want to parse anything again with getopts** |[OPTIND](../syntax/shellvars.md#OPTIND)|Holds the index to the next argument to be processed. This is how `getopts` "remembers" its own status between invocations. Also useful to shift the positional parameters after processing with `getopts`. `OPTIND` is initially set to 1, and **needs to be re-set to 1 if you want to parse anything again with getopts**
[OPTARG](../syntax/shellvars.md#OPTARG) This variable is set to any argument for an option found by `getopts`. It also contains the option flag of an unknown option. |[OPTARG](../syntax/shellvars.md#OPTARG)|This variable is set to any argument for an option found by `getopts`. It also contains the option flag of an unknown option.|
[OPTERR](../syntax/shellvars.md#OPTERR) (Values 0 or 1) Indicates if Bash should display error messages generated by the `getopts` builtin. The value is initialized to **1** on every shell startup - so be sure to always set it to **0** if you don't want to see annoying messages! **`OPTERR` is not specified by POSIX for the `getopts` builtin utility --- only for the C `getopt()` function in `unistd.h` (`opterr`).** `OPTERR` is bash-specific and not supported by shells such as ksh93, mksh, zsh, or dash. |[OPTERR](../syntax/shellvars.md#OPTERR)|(Values 0 or 1) Indicates if Bash should display error messages generated by the `getopts` builtin. The value is initialized to **1** on every shell startup - so be sure to always set it to **0** if you don't want to see annoying messages! **`OPTERR` is not specified by POSIX for the `getopts` builtin utility --- only for the C `getopt()` function in `unistd.h` (`opterr`).** `OPTERR` is bash-specific and not supported by shells such as ksh93, mksh, zsh, or dash.|
`getopts` also uses these variables for error reporting (they\'re set to `getopts` also uses these variables for error reporting (they're set to
value-combinations which arent possible in normal operation). value-combinations which arent possible in normal operation).
### Specify what you want ### Specify what you want
@ -114,10 +114,11 @@ The base-syntax for `getopts` is:
where: where:
`OPTSTRING` tells `getopts` which options to expect and where to expect arguments (see below) |Option|Description|
------------- ------------------------------------------------------------------------------------ |------|-----------|
`VARNAME` tells `getopts` which shell-variable to use for option reporting |`OPTSTRING`|tells `getopts` which options to expect and where to expect arguments (see below)|
`ARGS` tells `getopts` to parse these optional words instead of the positional parameters |`VARNAME`|tells `getopts` which shell-variable to use for option reporting|
|`ARGS`|tells `getopts` to parse these optional words instead of the positional parameters|
#### The option-string #### The option-string
@ -136,7 +137,7 @@ an argument (i.e. to become `-A SOMETHING`) just do:
If the **very first character** of the option-string is a `:` (colon), If the **very first character** of the option-string is a `:` (colon),
which would normally be nonsense because there's no option letter which would normally be nonsense because there's no option letter
preceding it, `getopts` switches to \"**silent error reporting mode**\". preceding it, `getopts` switches to "**silent error reporting mode**".
In productive scripts, this is usually what you want because it allows In productive scripts, this is usually what you want because it allows
you to handle errors yourself without being disturbed by annoying you to handle errors yourself without being disturbed by annoying
messages. messages.
@ -177,15 +178,17 @@ are indicated in an easier way.
#### Verbose Mode #### Verbose Mode
invalid option `VARNAME` is set to `?` (question-mark) and `OPTARG` is unset |failure|message|
----------------------------- ---------------------------------------------------------------------------------------------- |-------|-------|
required argument not found `VARNAME` is set to `?` (question-mark), `OPTARG` is unset and an *error message is printed* |invalid option|`VARNAME` is set to `?` (question-mark) and `OPTARG` is unset|
|required argument not found|`VARNAME` is set to `?` (question-mark), `OPTARG` is unset and an *error message is printed*|
#### Silent Mode #### Silent Mode
invalid option `VARNAME` is set to `?` (question-mark) and `OPTARG` is set to the (invalid) option character |failure|message|
----------------------------- ----------------------------------------------------------------------------------------------- |-------|-------|
required argument not found `VARNAME` is set to `:` (colon) and `OPTARG` contains the option-character in question |invalid option|`VARNAME` is set to `?` (question-mark) and `OPTARG` is set to the (invalid) option character|
|required argument not found|`VARNAME` is set to `:` (colon) and `OPTARG` contains the option-character in question|
## Using it ## Using it
@ -212,7 +215,7 @@ while getopts ":a" opt; do
done done
``` ```
I put that into a file named `go_test.sh`, which is the name you\'ll see I put that into a file named `go_test.sh`, which is the name you'll see
below in the examples. below in the examples.
Let's do some tests: Let's do some tests:
@ -220,7 +223,7 @@ Let's do some tests:
#### Calling it without any arguments #### Calling it without any arguments
$ ./go_test.sh $ ./go_test.sh
$ $
Nothing happened? Right. `getopts` didn't see any valid or invalid Nothing happened? Right. `getopts` didn't see any valid or invalid
options (letters preceded by a dash), so it wasn't triggered. options (letters preceded by a dash), so it wasn't triggered.
@ -228,7 +231,7 @@ options (letters preceded by a dash), so it wasn't triggered.
#### Calling it with non-option arguments #### Calling it with non-option arguments
$ ./go_test.sh /etc/passwd $ ./go_test.sh /etc/passwd
$ $
Again --- nothing happened. The **very same** case: `getopts` didn't Again --- nothing happened. The **very same** case: `getopts` didn't
see any valid or invalid options (letters preceded by a dash), so it see any valid or invalid options (letters preceded by a dash), so it
@ -245,7 +248,7 @@ First, an **invalid** one:
$ ./go_test.sh -b $ ./go_test.sh -b
Invalid option: -b Invalid option: -b
$ $
As expected, `getopts` didn't accept this option and acted like told As expected, `getopts` didn't accept this option and acted like told
above: It placed `?` into `$opt` and the invalid option character (`b`) above: It placed `?` into `$opt` and the invalid option character (`b`)
@ -255,7 +258,7 @@ Now, a **valid** one (`-a`):
$ ./go_test.sh -a $ ./go_test.sh -a
-a was triggered! -a was triggered!
$ $
You see, the detection works perfectly. The `a` was put into the You see, the detection works perfectly. The `a` was put into the
variable `$opt` for our case statement. variable `$opt` for our case statement.
@ -268,7 +271,7 @@ calling:
Invalid option: -x Invalid option: -x
Invalid option: -b Invalid option: -b
Invalid option: -c Invalid option: -c
$ $
Finally, it's of course possible, to give our option **multiple Finally, it's of course possible, to give our option **multiple
times**: times**:
@ -278,7 +281,7 @@ times**:
-a was triggered! -a was triggered!
-a was triggered! -a was triggered!
-a was triggered! -a was triggered!
$ $
The last examples lead us to some points you may consider: The last examples lead us to some points you may consider:
@ -319,14 +322,14 @@ Let's do the very same tests we did in the last example:
#### Calling it without any arguments #### Calling it without any arguments
$ ./go_test.sh $ ./go_test.sh
$ $
As above, nothing happened. It wasn't triggered. As above, nothing happened. It wasn't triggered.
#### Calling it with non-option arguments #### Calling it with non-option arguments
$ ./go_test.sh /etc/passwd $ ./go_test.sh /etc/passwd
$ $
The **very same** case: It wasn't triggered. The **very same** case: It wasn't triggered.
@ -336,7 +339,7 @@ The **very same** case: It wasn't triggered.
$ ./go_test.sh -b $ ./go_test.sh -b
Invalid option: -b Invalid option: -b
$ $
As expected, as above, `getopts` didn't accept this option and acted As expected, as above, `getopts` didn't accept this option and acted
like programmed. like programmed.
@ -345,7 +348,7 @@ like programmed.
$ ./go_test.sh -a $ ./go_test.sh -a
Option -a requires an argument. Option -a requires an argument.
$ $
The option was okay, but there is an argument missing. The option was okay, but there is an argument missing.

View File

@ -23,8 +23,8 @@ The basic procedure is simple: The script checks if a specific condition
doesn't start. doesn't start.
This article describes locking with common UNIX(r) tools. There are This article describes locking with common UNIX(r) tools. There are
other special locking tools available, But they\'re not standardized, or other special locking tools available, But they're not standardized, or
worse yet, you can't be sure they\'re present when you want to run your worse yet, you can't be sure they're present when you want to run your
scripts. **A tool designed for specifically for this purpose does the scripts. **A tool designed for specifically for this purpose does the
job much better than general purpose code.** job much better than general purpose code.**
@ -42,7 +42,7 @@ limits.
The best way to set a global lock condition is the UNIX(r) filesystem. The best way to set a global lock condition is the UNIX(r) filesystem.
Variables aren't enough, as each process has its own private variable Variables aren't enough, as each process has its own private variable
space, but the filesystem is global to all processes (yes, I know about space, but the filesystem is global to all processes (yes, I know about
chroots, namespaces, \... special case). You can \"set\" several things chroots, namespaces, ... special case). You can "set" several things
in the filesystem that can be used as locking indicator: in the filesystem that can be used as locking indicator:
- create files - create files
@ -61,7 +61,7 @@ they are succesfully locked, and can operate without colliding. Setting
the timestamp is similar: One step to check the timespamp, a second step the timestamp is similar: One step to check the timespamp, a second step
to set the timestamp. to set the timestamp.
<WRAP center round tip 60%> [**Conclusion:**]{.underline} We need an <WRAP center round tip 60%> <u>**Conclusion:**</u> We need an
operation that does the check and the locking in one step. </WRAP> operation that does the check and the locking in one step. </WRAP>
A simple way to get that is to create a **lock directory** - with the A simple way to get that is to create a **lock directory** - with the
@ -95,14 +95,14 @@ trapped. I am sure there there is a better solution than this
suggestion* --- **sn18** 2009/12/19 08:24* suggestion* --- **sn18** 2009/12/19 08:24*
**Note:** While perusing the Internet, I found some people asking if the **Note:** While perusing the Internet, I found some people asking if the
`mkdir` method works \"on all filesystems\". Well, let's say it should. `mkdir` method works "on all filesystems". Well, let's say it should.
The syscall under `mkdir` is guarenteed to work atomicly in all cases, The syscall under `mkdir` is guarenteed to work atomicly in all cases,
at least on Unices. Two examples of problems are NFS filesystems and at least on Unices. Two examples of problems are NFS filesystems and
filesystems on cluster servers. With those two scenarios, dependencies filesystems on cluster servers. With those two scenarios, dependencies
exist related to the mount options and implementation. However, I exist related to the mount options and implementation. However, I
successfully use this simple method on an Oracle OCFS2 filesystem in a successfully use this simple method on an Oracle OCFS2 filesystem in a
4-node cluster environment. So let's just say \"it should work under 4-node cluster environment. So let's just say "it should work under
normal conditions\". normal conditions".
Another atomic method is setting the `noclobber` shell option Another atomic method is setting the `noclobber` shell option
(`set -C`). That will cause redirection to fail, if the file the (`set -C`). That will cause redirection to fail, if the file the
@ -162,12 +162,12 @@ echo -n "[statsgen] Locking: " >&2
if mkdir "${LOCKDIR}" &>/dev/null; then if mkdir "${LOCKDIR}" &>/dev/null; then
# lock succeeded, install signal handlers before storing the PID just in case # lock succeeded, install signal handlers before storing the PID just in case
# storing the PID fails # storing the PID fails
trap 'ECODE=$?; trap 'ECODE=$?;
echo "[statsgen] Removing lock. Exit: ${ETXT[ECODE]}($ECODE)" >&2 echo "[statsgen] Removing lock. Exit: ${ETXT[ECODE]}($ECODE)" >&2
rm -rf "${LOCKDIR}"' 0 rm -rf "${LOCKDIR}"' 0
echo "$$" >"${PIDFILE}" echo "$$" >"${PIDFILE}"
# the following handler will exit the script upon receiving these signals # the following handler will exit the script upon receiving these signals
# the trap on "0" (EXIT) from above will be triggered by this trap's "exit" command! # the trap on "0" (EXIT) from above will be triggered by this trap's "exit" command!
trap 'echo "[statsgen] Killed by a signal." >&2 trap 'echo "[statsgen] Killed by a signal." >&2

View File

@ -35,7 +35,7 @@ anymore.
### Operation modes ### Operation modes
There are four basic operation modes to *list*, *read*, *write* and There are four basic operation modes to *list*, *read*, *write* and
*copy* archives. They\'re switched with combinations of `-r` and `-w` *copy* archives. They're switched with combinations of `-r` and `-w`
command line options: command line options:
Mode RW-Options Mode RW-Options
@ -123,7 +123,7 @@ files to list or extract.
- if you specify the `-c` option, `pax` will invert the matches, i.e. - if you specify the `-c` option, `pax` will invert the matches, i.e.
it matches all filenames **except** those matching the specified it matches all filenames **except** those matching the specified
patterns patterns
- if no patterns are given, `pax` will \"match\" (list or extract) all - if no patterns are given, `pax` will "match" (list or extract) all
files from the archive files from the archive
- **To avoid conflicts with shell pathname expansion, it's wise to - **To avoid conflicts with shell pathname expansion, it's wise to
quote patterns!** quote patterns!**
@ -207,7 +207,7 @@ To copy directory contents to another directory, similar to a `cp -a`
command, use: command, use:
mkdir destdir mkdir destdir
pax -rw dir destdir #creates a copy of dir in destdir/, i.e. destdir/dir pax -rw dir destdir #creates a copy of dir in destdir/, i.e. destdir/dir
### Copying files via ssh ### Copying files via ssh
@ -223,7 +223,7 @@ on the remote machine.
### Backup your daily work ### Backup your daily work
[**Note:**]{.underline} `-T` is an extension and is not defined by <u>**Note:**</u> `-T` is an extension and is not defined by
POSIX. POSIX.
Say you have write-access to a fileserver mounted on your filesystem Say you have write-access to a fileserver mounted on your filesystem
@ -234,14 +234,14 @@ modified today:
pax -rw -T 0000 data/ /n/mybackups/$(date +%A)/ pax -rw -T 0000 data/ /n/mybackups/$(date +%A)/
This is done using the `-T` switch, which normally allows you to specify This is done using the `-T` switch, which normally allows you to specify
a time window, but in this case, only the start time which means \"today a time window, but in this case, only the start time which means "today
at midnight\". at midnight".
When you execute this \"very simple backup\" after your daily work, you When you execute this "very simple backup" after your daily work, you
will have a copy of the modified files. will have a copy of the modified files.
[**Note:**]{.underline} The `%A` format from `date` expands to the name <u>**Note:**</u> The `%A` format from `date` expands to the name
of the current day, localized, e.g. \"Friday\" (en) or \"Mittwoch\" of the current day, localized, e.g. "Friday" (en) or "Mittwoch"
(de). (de).
The same, but with an archive, can be accomplished by: The same, but with an archive, can be accomplished by:
@ -282,19 +282,19 @@ The -s command seen above can be used to exclude a file. The
substitution must result in a null string: For example, let's say that substitution must result in a null string: For example, let's say that
you want to exclude all the CVS directories to create a source code you want to exclude all the CVS directories to create a source code
archive. We are going to replace the names containing /CVS/ with archive. We are going to replace the names containing /CVS/ with
nothing, note the .\* they are needed because we need to match the nothing, note the `.*` they are needed because we need to match the
entire pathname. entire pathname.
pax -w -x ustar -f release.tar -s',.*/CVS/.*,,' myapplication pax -w -x ustar -f release.tar -s',.*/CVS/.*,,' myapplication
You can use several -s options, for instance, let's say you also want You can use several -s options, for instance, let's say you also want
to remove files ending in \~: to remove files ending in `~`:
pax -w -x ustar -f release.tar -'s,.*/CVS/.*,,' -'s/.*~//' myapplication pax -w -x ustar -f release.tar -'s,.*/CVS/.*,,' -'s/.*~//' myapplication
This can also be done while reading an archive, for instance, suppose This can also be done while reading an archive, for instance, suppose
you have an archive containing a \"usr\" and a \"etc\" directory but you have an archive containing a "usr" and a "etc" directory but
that you want to extract only the \"usr\" directory: that you want to extract only the "usr" directory:
pax -r -f archive.tar -s',^etc/.*,,' #the etc/ dir is not extracted pax -r -f archive.tar -s',^etc/.*,,' #the etc/ dir is not extracted
@ -341,8 +341,8 @@ make the switch:
------------------------------------- ------------------------------------------ ----------------------------------------------------------------------- ------------------------------------- ------------------------------------------ -----------------------------------------------------------------------
`tar xzvf file.tar.gz` `pax -rvz -f file.tar.gz` `-z` is an extension, POSIXly: `gunzip <file.tar.gz | pax -rv` `tar xzvf file.tar.gz` `pax -rvz -f file.tar.gz` `-z` is an extension, POSIXly: `gunzip <file.tar.gz | pax -rv`
`tar czvf archive.tar.gz path ...` `pax -wvz -f archive.tar.gz path ...` `-z` is an extension, POSIXly: `pax -wv path | gzip > archive.tar.gz` `tar czvf archive.tar.gz path ...` `pax -wvz -f archive.tar.gz path ...` `-z` is an extension, POSIXly: `pax -wv path | gzip > archive.tar.gz`
`tar xjvf file.tar.bz2` `bunzip2 <file.tar.bz2 | pax -rv` `tar xjvf file.tar.bz2` `bunzip2 <file.tar.bz2 | pax -rv`
`tar cjvf archive.tar.bz2 path ...` `pax -wv path | bzip2 > archive.tar.bz2` `tar cjvf archive.tar.bz2 path ...` `pax -wv path | bzip2 > archive.tar.bz2`
`tar tzvf file.tar.gz` `pax -vz -f file.tar.gz` `-z` is an extension, POSIXly: `gunzip <file.tar.gz | pax -v` `tar tzvf file.tar.gz` `pax -vz -f file.tar.gz` `-z` is an extension, POSIXly: `gunzip <file.tar.gz | pax -v`
`pax` might not create ustar (`tar`) archives by default but its own pax `pax` might not create ustar (`tar`) archives by default but its own pax

View File

@ -13,7 +13,7 @@ tags:
# Illustrated Redirection Tutorial # Illustrated Redirection Tutorial
This tutorial is not a complete guide to redirection, it will not cover This tutorial is not a complete guide to redirection, it will not cover
here docs, here strings, name pipes etc\... I just hope it\'ll help you here docs, here strings, name pipes etc... I just hope it'll help you
to understand what things like `3>&2`, `2>&1` or `1>&3-` do. to understand what things like `3>&2`, `2>&1` or `1>&3-` do.
# stdin, stdout, stderr # stdin, stdout, stderr
@ -22,7 +22,7 @@ When Bash starts, normally, 3 file descriptors are opened, `0`, `1` and
`2` also known as standard input (`stdin`), standard output (`stdout`) `2` also known as standard input (`stdin`), standard output (`stdout`)
and standard error (`stderr`). and standard error (`stderr`).
For example, with Bash running in a Linux terminal emulator, you\'ll For example, with Bash running in a Linux terminal emulator, you'll
see: see:
# lsof +f g -ap $BASHPID -d 0,1,2 # lsof +f g -ap $BASHPID -d 0,1,2
@ -54,7 +54,7 @@ connected to `/dev/pts/5`.
# Simple Redirections # Simple Redirections
## Output Redirection \"n> file\" ## Output Redirection "n&gt; file"
`>` is probably the simplest redirection. `>` is probably the simplest redirection.
@ -107,7 +107,7 @@ pointing to `file`. The command will then start with:
What will the command do with this descriptor? It depends. Often What will the command do with this descriptor? It depends. Often
nothing. We will see later why we might want other file descriptors. nothing. We will see later why we might want other file descriptors.
## Input Redirection \"n< file\" ## Input Redirection "n&lt; file"
When you run a commandusing `command < file`, it changes the file When you run a commandusing `command < file`, it changes the file
descriptor `0` so that it looks like: descriptor `0` so that it looks like:
@ -130,7 +130,7 @@ from the console.
As with `>`, `<` can be used to open a new file descriptor for reading, As with `>`, `<` can be used to open a new file descriptor for reading,
`command 3<file`. Later we will see how this can be useful. `command 3<file`. Later we will see how this can be useful.
## Pipes \| ## Pipes |
What does this `|` do? Among other things, it connects the standard What does this `|` do? Among other things, it connects the standard
output of the command on the left to the standard input of the command output of the command on the left to the standard input of the command
@ -181,8 +181,8 @@ interesting example so we will use `ls /tmp/ doesnotexist 2>&1 | less`
--- +--------------+ --- +--------------+ --- +--------------+ --- +--------------+
Why is it called *duplicating*? Because after `2>&1`, we have 2 file Why is it called *duplicating*? Because after `2>&1`, we have 2 file
descriptors pointing to the same file. Take care not to call this \"File descriptors pointing to the same file. Take care not to call this "File
Descriptor Aliasing\"; if we redirect `stdout` after `2>&1` to a file Descriptor Aliasing"; if we redirect `stdout` after `2>&1` to a file
`B`, file descriptor `2` will still be opened on the file `A` where it `B`, file descriptor `2` will still be opened on the file `A` where it
was. This is often misunderstood by people wanting to redirect both was. This is often misunderstood by people wanting to redirect both
standard input and standard output to the file. Continue reading for standard input and standard output to the file. Continue reading for
@ -223,9 +223,10 @@ Similarly for output file descriptors, writing a line to file descriptor
`s` will append a line to a file as will writing a line to file `s` will append a line to a file as will writing a line to file
descriptor `t`. descriptor `t`.
<note tip>The syntax is somewhat confusing in that you would think !!! info "Tip"
that the arrow would point in the direction of the copy, but it's The syntax is somewhat confusing in that you would think
reversed. So it's `target>&source` effectively.</note> that the arrow would point in the direction of the copy, but it's
reversed. So it's `target>&source` effectively.
So, as a simple example (albeit slightly contrived), is the following: So, as a simple example (albeit slightly contrived), is the following:
@ -235,7 +236,7 @@ So, as a simple example (albeit slightly contrived), is the following:
exec 1>&3 # Copy 3 back into 1 exec 1>&3 # Copy 3 back into 1
echo Done # Output to original stdout echo Done # Output to original stdout
## Order Of Redirection, i.e., \"> file 2>&1\" vs. \"2>&1 >file\" ## Order Of Redirection, i.e., "`> file 2>&1`" vs. "`2>&1 >file`"
While it doesn't matter where the redirections appears on the command While it doesn't matter where the redirections appears on the command
line, their order does matter. They are set up from left to right. line, their order does matter. They are set up from left to right.
@ -323,7 +324,7 @@ Then it sees our duplication `2>&1`:
And voila, both `1` and `2` are redirected to file. And voila, both `1` and `2` are redirected to file.
## Why sed 's/foo/bar/\' file >file Doesn't Work ## Why sed 's/foo/bar/' file >file Doesn't Work
This is a common error, we want to modify a file using something that This is a common error, we want to modify a file using something that
reads from a file and writes the result to `stdout`. To do this, we reads from a file and writes the result to `stdout`. To do this, we
@ -332,7 +333,7 @@ as we have seen, the redirections are setup before the command is
actually executed. actually executed.
So **BEFORE** sed starts, standard output has already been redirected, So **BEFORE** sed starts, standard output has already been redirected,
with the additional side effect that, because we used >, \"file\" gets with the additional side effect that, because we used >, "file" gets
truncated. When `sed` starts to read the file, it contains nothing. truncated. When `sed` starts to read the file, it contains nothing.
## exec ## exec
@ -447,8 +448,8 @@ it. It's probably better to do something like:
#we don't need 3 any more #we don't need 3 any more
I\'ve seen some people using this as a way to discard, say stderr, using I've seen some people using this as a way to discard, say stderr, using
something like: command 2>&-. Though it might work, I\'m not sure if something like: command 2>&-. Though it might work, I'm not sure if
you can expect all applications to behave correctly with a closed you can expect all applications to behave correctly with a closed
stderr. stderr.
@ -598,11 +599,11 @@ original `stderr`.
# Syntax # Syntax
I used to have trouble choosing between `0&<3` `3&>1` `3>&1` `->2` I used to have trouble choosing between `0&<3` `3&>1` `3>&1` `->2`
`-<&0` `&-<0` `0<&-` etc\... (I think probably because the syntax is `-<&0` `&-<0` `0<&-` etc... (I think probably because the syntax is
more representative of the result, i.e., the redirection, than what is more representative of the result, i.e., the redirection, than what is
done, i.e., opening, closing, or duplicating file descriptors). done, i.e., opening, closing, or duplicating file descriptors).
If this fits your situation, then maybe the following \"rules\" will If this fits your situation, then maybe the following "rules" will
help you, a redirection is always like the following: help you, a redirection is always like the following:
lhs op rhs lhs op rhs
@ -612,18 +613,12 @@ help you, a redirection is always like the following:
the op is `<` then there is an implicit 0, if it's `>` or `>>`, the op is `<` then there is an implicit 0, if it's `>` or `>>`,
there is an implicit 1. there is an implicit 1.
```{=html}
<!-- -->
```
- `op` is `<`, `>`, `>>`, `>|`, or `<>`: - `op` is `<`, `>`, `>>`, `>|`, or `<>`:
- `<` if the file decriptor in `lhs` will be read, `>` if it will - `<` if the file decriptor in `lhs` will be read, `>` if it will
be written, `>>` if data is to be appended to the file, `>|` to be written, `>>` if data is to be appended to the file, `>|` to
overwrite an existing file or `<>` if it will be both read and overwrite an existing file or `<>` if it will be both read and
written. written.
```{=html}
<!-- -->
```
- `rhs` is the thing that the file descriptor will describe: - `rhs` is the thing that the file descriptor will describe:
- It can be the name of a file, the place where another descriptor - It can be the name of a file, the place where another descriptor
goes (`&1`), or, `&-`, which will close the file descriptor. goes (`&1`), or, `&-`, which will close the file descriptor.
@ -638,49 +633,34 @@ The shell is pretty loose about what it considers a valid redirect.
While opinions probably differ, this author has some (strong) While opinions probably differ, this author has some (strong)
recommendations: recommendations:
- **Always** keep redirections \"tightly grouped\" -- that is, **do - **Always** keep redirections "tightly grouped" -- that is, **do
not** include whitespace anywhere within the redirection syntax not** include whitespace anywhere within the redirection syntax
except within quotes if required on the RHS (e.g. a filename that except within quotes if required on the RHS (e.g. a filename that
contains a space). Since shells fundamentally use whitespace to contains a space). Since shells fundamentally use whitespace to
delimit fields in general, it is visually much clearer for each delimit fields in general, it is visually much clearer for each
redirection to be separated by whitespace, but grouped in chunks redirection to be separated by whitespace, but grouped in chunks
that contain no unnecessary whitespace. that contain no unnecessary whitespace.
```{=html}
<!-- -->
```
- **Do** always put a space between each redirection, and between the - **Do** always put a space between each redirection, and between the
argument list and the first redirect.
```{=html}
<!-- -->
```
- **Always** place redirections together at the very end of a command - **Always** place redirections together at the very end of a command
after all arguments. Never precede a command with a redirect. Never after all arguments. Never precede a command with a redirect. Never
put a redirect in the middle of the arguments.
```{=html}
<!-- -->
```
- **Never** use the Csh `&>foo` and `>&foo` shorthand redirects. Use - **Never** use the Csh `&>foo` and `>&foo` shorthand redirects. Use
the long form `>foo 2>&1`. (see: [obsolete](../scripting/obsolete.md)) the long form `>foo 2>&1`. (see: [obsolete](../scripting/obsolete.md))
```{=html} ```bash
<!-- --> # Good! This is clearly a simple commmand with two arguments and 4 redirections
cmd arg1 arg2 <myFile 3<&1 2>/dev/null >&2
# Good!
{ cmd1 <<<'my input'; cmd2; } >someFile
# Bad. Is the "1" a file descriptor or an argument to cmd? (answer: it's the FD). Is the space after the herestring part of the input data? (answer: No).
# The redirects are also not delimited in any obvious way.
cmd 2>& 1 <<< stuff
# Hideously Bad. It's difficult to tell where the redirects are and whether they're even valid redirects.
# This is in fact one command with one argument, an assignment, and three redirects.
foo=bar<baz bork<<< blarg>bleh
``` ```
# Good! This is clearly a simple commmand with two arguments and 4 redirections
cmd arg1 arg2 <myFile 3<&1 2>/dev/null >&2
# Good!
{ cmd1 <<<'my input'; cmd2; } >someFile
# Bad. Is the "1" a file descriptor or an argument to cmd? (answer: it's the FD). Is the space after the herestring part of the input data? (answer: No).
# The redirects are also not delimited in any obvious way.
cmd 2>& 1 <<< stuff
# Hideously Bad. It's difficult to tell where the redirects are and whether they're even valid redirects.
# This is in fact one command with one argument, an assignment, and three redirects.
foo=bar<baz bork<<< blarg>bleh
# Conclusion # Conclusion
@ -689,9 +669,9 @@ I hope this tutorial worked for you.
I lied, I did not explain `1>&3-`, go check the manual ;-) I lied, I did not explain `1>&3-`, go check the manual ;-)
Thanks to Stéphane Chazelas from whom I stole both the intro and the Thanks to Stéphane Chazelas from whom I stole both the intro and the
example\.... example....
The intro is inspired by this introduction, you\'ll find a nice exercise The intro is inspired by this introduction, you'll find a nice exercise
there too: there too:
- [A Detailed Introduction to I/O and I/O - [A Detailed Introduction to I/O and I/O

View File

@ -23,7 +23,7 @@ We have a simple **stat.sh** script:
echo "PYTHON LINES: $LINES" echo "PYTHON LINES: $LINES"
This script evaluate the number of python files and the number of python This script evaluate the number of python files and the number of python
code lines in the files. We can use it like **./stat.sh <dir>** code lines in the files. We can use it like **`./stat.sh <dir>`**
### Create testsuit ### Create testsuit

View File

@ -11,7 +11,7 @@ tags:
# List of shell options # List of shell options
This information was taken from a Bash version \"`4.1`\", every now and This information was taken from a Bash version "`4.1`", every now and
then new options are added, so likely, this list isn't complete. then new options are added, so likely, this list isn't complete.
The shell-options can be set with the [shopt builtin The shell-options can be set with the [shopt builtin
@ -21,35 +21,35 @@ command](../commands/builtin/shopt.md).
### autocd ### autocd
Option: `autocd` Since: 4.0-alpha | Option: | `autocd` | Since: | 4.0-alpha |
------------- ------------------ ---------- ----------- |:------------|:-----------------|:---------|:----------|
Shell mode: interactive only Default: off | Shell mode: | interactive only | Default: | off |
If set, a command name that is the name of a directory is executed as if If set, a command name that is the name of a directory is executed as if
it were the argument to the cd command. it were the argument to the cd command.
### assoc_expand_once ### assoc_expand_once
Option: `assoc_expand_once` Since: 5.0-alpha | Option: | `assoc_expand_once` | Since: | 5.0-alpha |
------------- --------------------- ---------- ----------- |:------------|:--------------------|:---------|:----------|
Shell mode: all Default: off | Shell mode: | all | Default: | off |
If set, Bash attempts to expand associative array options only once. If set, Bash attempts to expand associative array options only once.
### cdable_vars ### cdable_vars
Option: `cdable_vars` Since: unknown | Option: | `cdable_vars` | Since: | unknown |
------------- --------------- ---------- --------- |:------------|:--------------|:---------|:--------|
Shell mode: all Default: off | Shell mode: | all | Default: | off |
Treat every **non-directory argument** to the `cd`-command as variable Treat every **non-directory argument** to the `cd`-command as variable
name containing a directory to `cd` into. name containing a directory to `cd` into.
### cdspell ### cdspell
Option: `cdspell` Since: unknown | Option: | `cdspell` | Since: | unknown |
------------- ------------------ ---------- --------- |:------------|:-----------------|:---------|:--------|
Shell mode: interactive only Default: off | Shell mode: | interactive only | Default: | off |
If set, minor errors in the spelling of a directory component in a cd If set, minor errors in the spelling of a directory component in a cd
command will be corrected. The errors checked for are transposed command will be corrected. The errors checked for are transposed
@ -59,9 +59,9 @@ proceeds.
### checkhash ### checkhash
Option: `checkhash` Since: unknown | Option: | `checkhash` | Since: | unknown |
------------- ------------- ---------- --------- |:------------|:------------|:---------|:--------|
Shell mode: all Default: off | Shell mode: | all | Default: | off |
If set, Bash checks that a command found in the hash table exists before If set, Bash checks that a command found in the hash table exists before
trying to execute it. If a hashed command no longer exists, a normal trying to execute it. If a hashed command no longer exists, a normal
@ -69,9 +69,9 @@ path search is performed.
### checkjobs ### checkjobs
Option: `checkjobs` Since: 4.0-alpha | Option: | `checkjobs` | Since: | 4.0-alpha |
------------- ------------------ ---------- ----------- |:------------|:-----------------|:---------|:----------|
Shell mode: interactive only Default: off | Shell mode: | interactive only | Default: | off |
If set, Bash lists the status of any stopped and running jobs before If set, Bash lists the status of any stopped and running jobs before
exiting an interactive shell. If any jobs are running, this causes the exiting an interactive shell. If any jobs are running, this causes the
@ -81,9 +81,9 @@ stopped.
### checkwinsize ### checkwinsize
Option: `checkwinsize` Since: unknown | Option: | `checkwinsize` | Since: | unknown |
------------- ---------------- ---------- --------- |:------------|:---------------|:---------|:--------|
Shell mode: all Default: on | Shell mode: | all | Default: | on |
If set, Bash checks the window size after each command and, if If set, Bash checks the window size after each command and, if
necessary, updates the values of the variables necessary, updates the values of the variables
@ -92,9 +92,9 @@ necessary, updates the values of the variables
### cmdhist ### cmdhist
Option: `cmdhist` Since: unknown | Option: | `cmdhist` | Since: | unknown |
------------- ----------- ---------- --------- |:------------|:----------|:---------|:--------|
Shell mode: all Default: off | Shell mode: | all | Default: | off |
If set, Bash attempts to save all lines of a multiple-line command in If set, Bash attempts to save all lines of a multiple-line command in
the same history entry. This allows easy re-editing of multi-line the same history entry. This allows easy re-editing of multi-line
@ -102,65 +102,64 @@ commands.
### compat31 ### compat31
Option: `compat31` Since: 3.2 | Option: | `compat31` | Since: | 3.2 |
------------- ------------ ---------- ----- |:------------|:-----------|:---------|:----|
Shell mode: all Default: off | Shell mode: | all | Default: | off |
Compatiblity mode for Bash 3.1 Compatiblity mode for Bash 3.1
### compat32 ### compat32
Option: `compat32` Since: 4.0 | Option: | `compat32` | Since: | 4.0 |
------------- ------------ ---------- ----- |:------------|:-----------|:---------|:----|
Shell mode: all Default: off | Shell mode: | all | Default: | off |
Compatiblity mode for Bash 3.2 Compatiblity mode for Bash 3.2
### compat40 ### compat40
Option: `compat40` Since: 4.1-beta | Option: | `compat40` | Since: | 4.1-beta |
------------- ------------ ---------- ---------- |:------------|:-----------|:---------|:---------|
Shell mode: all Default: off | Shell mode: | all | Default: | off |
Compatiblity mode for Bash 4.0 Compatiblity mode for Bash 4.0
### compat41 ### compat41
Option: `compat41` Since: 4.2-alpha | Option: | `compat41` | Since: | 4.2-alpha |
------------- ------------ ---------- ----------- |:------------|:-----------|:---------|:----------|
Shell mode: all Default: off | Shell mode: | all | Default: | off |
Compatiblity mode for Bash 4.1 Compatiblity mode for Bash 4.1
### compat42 ### compat42
Option: `compat42` Since: 4.3-alpha | Option: | `compat42` | Since: | 4.3-alpha |
------------- ------------ ---------- ----------- |:------------|:-----------|:---------|:----------|
Shell mode: all Default: off | Shell mode: | all | Default: | off |
Compatiblity mode for Bash 4.2 Compatiblity mode for Bash 4.2
### compat43 ### compat43
Option: `compat43` Since: 4.4-alpha | Option: | `compat43` | Since: | 4.4-alpha |
------------- ------------ ---------- ----------- |:------------|:-----------|:---------|:----------|
Shell mode: all Default: off | Shell mode: | all | Default: | off |
Compatiblity mode for Bash 4.3 Compatiblity mode for Bash 4.3
### compat44 ### compat44
Option: `compat44` Since: 5.0-alpha | Option: | `compat44` | Since: | 5.0-alpha |
------------- ------------ ---------- ----------- |:------------|:-----------|:---------|:----------|
Shell mode: all Default: off | Shell mode: | all | Default: | off |
Compatiblity mode for Bash 4.4 Compatiblity mode for Bash 4.4
### direxpand ### direxpand
Option: `direxpand` Since: 4.3-alpha | Option: | `direxpand` | Since: | 4.3-alpha |
------------- ------------- ---------- ------------------------------------------------------------------------ |:------------|:------------|:---------|:-----------------------------------------------------------------------|
Shell mode: all Default: off (unless changed on compile-time with `--enable-direxpand-default`) | Shell mode: | all | Default: | off (unless changed on compile-time with `--enable-direxpand-default`) |
If set, bash replaces directory names with the results of word expansion If set, bash replaces directory names with the results of word expansion
when performing filename completion. This changes the contents of the when performing filename completion. This changes the contents of the
@ -169,27 +168,27 @@ user typed.
### dirspell ### dirspell
Option: `dirspell` Since: 4.0-alpha | Option: | `dirspell` | Since: | 4.0-alpha |
------------- ------------ ---------- ----------- |:------------|:-----------|:---------|:----------|
Shell mode: all Default: off | Shell mode: | all | Default: | off |
If set, Bash will perform spelling corrections on directory names to If set, Bash will perform spelling corrections on directory names to
match a glob. match a glob.
### dotglob ### dotglob
Option: `dotglob` Since: unknown | Option: | `dotglob` | Since: | unknown |
------------- ----------- ---------- --------- |:------------|:----------|:---------|:--------|
Shell mode: all Default: off | Shell mode: | all | Default: | off |
If set, Bash includes filenames beginning with a `.` (dot) in the If set, Bash includes filenames beginning with a `.` (dot) in the
results of [pathname expansion](../syntax/expansion/globs.md). results of [pathname expansion](../syntax/expansion/globs.md).
### execfail ### execfail
Option: `execfail` Since: unknown | Option: | `execfail` | Since: | unknown |
------------- ----------------- ---------- --------- |:------------|:----------------|:---------|:--------|
Shell mode: non-interactive Default: off | Shell mode: | non-interactive | Default: | off |
If set, a non-interactive shell will not exit if it cannot execute the If set, a non-interactive shell will not exit if it cannot execute the
file specified as an argument to the `exec`-builtin command. An file specified as an argument to the `exec`-builtin command. An
@ -197,26 +196,26 @@ interactive shell does not exit if `exec` fails.
### expand_aliases ### expand_aliases
Option: `expand_aliases` Since: unknown | Option: | `expand_aliases` | Since: | unknown |
------------- ------------------ ---------- ----------------------------------------- |:------------|:-----------------|:---------|:----------------------------------------|
Shell mode: all Default: on (interactive), off (non-interactive) | Shell mode: | all | Default: | on (interactive), off (non-interactive) |
If set, aliases are expanded. This option is enabled by default for If set, aliases are expanded. This option is enabled by default for
interactive shells. interactive shells.
### extdebug ### extdebug
Option: `extdebug` Since: 3.0-alpha | Option: | `extdebug` | Since: | 3.0-alpha |
------------- ------------ ---------- ----------- |:------------|:-----------|:---------|:----------|
Shell mode: all Default: off | Shell mode: | all | Default: | off |
If set, behavior intended for use by debuggers is enabled. If set, behavior intended for use by debuggers is enabled.
### extglob ### extglob
Option: `extglob` Since: 2.02-alpha1 | Option: | `extglob` | Since: | 2.02-alpha1 |
------------- ----------- ---------- ------------- |:------------|:----------|:---------|:------------|
Shell mode: all Default: off | Shell mode: | all | Default: | off |
If set, the extended [pattern matching](../syntax/pattern.md) features are If set, the extended [pattern matching](../syntax/pattern.md) features are
enabled. See the important note below under [Parser enabled. See the important note below under [Parser
@ -224,9 +223,9 @@ configurations](#parser_configurations).
### extquote ### extquote
Option: `extquote` Since: 3.0-alpha (?) | Option: | `extquote` | Since: | 3.0-alpha (?) |
------------- ------------ ---------- --------------- |:------------|:-----------|:---------|:--------------|
Shell mode: all Default: on | Shell mode: | all | Default: | on |
If set, `$'string'` and `$"string"` quoting is performed within If set, `$'string'` and `$"string"` quoting is performed within
[parameter expansions](../syntax/pe.md) enclosed in double quotes. See the [parameter expansions](../syntax/pe.md) enclosed in double quotes. See the
@ -235,18 +234,18 @@ configurations](#parser_configurations).
### failglob ### failglob
Option: `failglob` Since: 3.0-alpha | Option: | `failglob` | Since: | 3.0-alpha |
------------- ------------ ---------- ----------- |:------------|:-----------|:---------|:----------|
Shell mode: all Default: off | Shell mode: | all | Default: | off |
If set, patterns which fail to match filenames during pathname expansion If set, patterns which fail to match filenames during pathname expansion
result in an error message. result in an error message.
### force_fignore ### force_fignore
Option: `force_fignore` Since: 3.0-alpha | Option: | `force_fignore` | Since: | 3.0-alpha |
------------- ----------------- ---------- ----------- |:------------|:----------------|:---------|:----------|
Shell mode: interactive Default: on | Shell mode: | interactive | Default: | on |
If set, the suffixes specified by the If set, the suffixes specified by the
[FIGNORE](../syntax/shellvars.md#FIGNORE) shell variable cause words to be [FIGNORE](../syntax/shellvars.md#FIGNORE) shell variable cause words to be
@ -255,9 +254,9 @@ the only possible completions. This option is enabled by default.
### globasciiranges ### globasciiranges
Option: `globasciiranges` Since: 4.3-alpha | Option: | `globasciiranges` | Since: | 4.3-alpha |
------------- ------------------- ---------- ----------------------------------- |:------------|:------------------|:---------|:----------------------------------|
Shell mode: all Default: on (configurable at compile time) | Shell mode: | all | Default: | on (configurable at compile time) |
If set, range expressions used in pattern matching behave as if in the If set, range expressions used in pattern matching behave as if in the
traditional C locale when performing comparisons. That is, the current traditional C locale when performing comparisons. That is, the current
@ -267,26 +266,26 @@ will collate together.
### globstar ### globstar
Option: `globstar` Since: 4.0-alpha | Option: | `globstar` | Since: | 4.0-alpha |
------------- ------------ ---------- ----------- |:------------|:-----------|:---------|:----------|
Shell mode: all Default: off | Shell mode: | all | Default: | off |
If set, recursive globbing with `**` is enabled. If set, recursive globbing with `**` is enabled.
### gnu_errfmt ### gnu_errfmt
Option: `gnu_errfmt` Since: 3.0-alpha | Option: | `gnu_errfmt` | Since: | 3.0-alpha |
------------- -------------- ---------- ----------- |:------------|:-------------|:---------|:----------|
Shell mode: all Default: off | Shell mode: | all | Default: | off |
If set, shell error messages are written in the \"standard GNU error If set, shell error messages are written in the "standard GNU error
message format\". message format".
### histappend ### histappend
Option: `histappend` Since: unknown | Option: | `histappend` | Since: | unknown |
------------- ----------------- ---------- --------- |:------------|:----------------|:---------|:--------|
Shell mode: interactive (?) Default: off | Shell mode: | interactive (?) | Default: | off |
If set, the history list is appended to the file named by the value of If set, the history list is appended to the file named by the value of
the [HISTFILE](../syntax/shellvars.md#HISTFILE) variable when the shell the [HISTFILE](../syntax/shellvars.md#HISTFILE) variable when the shell
@ -294,53 +293,53 @@ exits, rather than overwriting the file.
### histreedit ### histreedit
Option: `histreedit` Since: unknown | Option: | `histreedit` | Since: | unknown |
------------- ----------------- ---------- --------- |:------------|:----------------|:---------|:--------|
Shell mode: interactive (?) Default: off | Shell mode: | interactive (?) | Default: | off |
If set, and readline is being used, a user is given the opportunity to If set, and readline is being used, a user is given the opportunity to
re-edit a failed history substitution. re-edit a failed history substitution.
### histverify ### histverify
Option: `histverify` Since: unknown | Option: | `histverify` | Since: | unknown |
------------- ----------------- ---------- --------- |:------------|:----------------|:---------|:--------|
Shell mode: interactive (?) Default: off | Shell mode: | interactive (?) | Default: | off |
Allow to review a history substitution result by loading the resulting Allow to review a history substitution result by loading the resulting
line into the editing buffer, rather than directly executing it. line into the editing buffer, rather than directly executing it.
### hostcomplete ### hostcomplete
Option: `hostcomplete` Since: 2.0-alpha3 | Option: | `hostcomplete` | Since: | 2.0-alpha3 |
------------- ----------------- ---------- ------------ |:------------|:----------------|:---------|:-----------|
Shell mode: interactive (?) Default: on | Shell mode: | interactive (?) | Default: | on |
If set, Bash completion also completes hostnames. On by default. If set, Bash completion also completes hostnames. On by default.
### huponexit ### huponexit
Option: `huponexit` Since: 2.02-alpha1 | Option: | `huponexit` | Since: | 2.02-alpha1 |
------------- ------------------- ---------- ------------- |:------------|:------------------|:---------|:------------|
Shell mode: interactive login Default: off | Shell mode: | interactive login | Default: | off |
If set, Bash will send the `SIGHUP` signal to all jobs when an If set, Bash will send the `SIGHUP` signal to all jobs when an
interactive login shell exits. interactive login shell exits.
### interactive_comments ### interactive_comments
Option: `interactive_comments` Since: unknown | Option: | `interactive_comments` | Since: | unknown |
------------- ------------------------ ---------- --------- |:------------|:-----------------------|:---------|:--------|
Shell mode: interactive Default: on | Shell mode: | interactive | Default: | on |
Allow [commenting](../scripting/basics.md#comments) in interactive shells, on Allow [commenting](../scripting/basics.md#comments) in interactive shells, on
by default. by default.
### lastpipe ### lastpipe
Option: `lastpipe` Since: 4.2-alpha | Option: | `lastpipe` | Since: | 4.2-alpha |
------------- ------------ ---------- ----------- |:------------|:-----------|:---------|:----------|
Shell mode: all Default: off | Shell mode: | all | Default: | off |
If set, **and job control is not active**, the shell runs the last If set, **and job control is not active**, the shell runs the last
command of a pipeline not executed in the background in the current command of a pipeline not executed in the background in the current
@ -348,9 +347,9 @@ shell environment.
### lithist ### lithist
Option: `lithist` Since: unknown | Option: | `lithist` | Since: | unknown |
------------- ------------- ---------- --------- |:------------|:------------|:---------|:--------|
Shell mode: interactive Default: off | Shell mode: | interactive | Default: | off |
If set, and the [#cmdhist](#cmdhist) option is enabled, multi-line If set, and the [#cmdhist](#cmdhist) option is enabled, multi-line
commands are saved to the history with embedded newlines rather than commands are saved to the history with embedded newlines rather than
@ -358,36 +357,36 @@ using semicolon separators where possible.
### localvar_inherit ### localvar_inherit
Option: `localvar_inherit` Since: 5.0-alpha | Option: | `localvar_inherit` | Since: | 5.0-alpha |
------------- -------------------- ---------- ----------- |:------------|:-------------------|:---------|:----------|
Shell mode: all Default: off | Shell mode: | all | Default: | off |
If this option is set, a local variable inherits the value of a variable If this option is set, a local variable inherits the value of a variable
with the same name at the nearest preceding scope. with the same name at the nearest preceding scope.
### login_shell ### login_shell
Option: `login_shell` Since: 2.05a-alpha1 | Option: | `login_shell` | Since: | 2.05a-alpha1 |
------------- --------------- ---------- -------------- |:------------|:--------------|:---------|:-------------|
Shell mode: all Default: n/a | Shell mode: | all | Default: | n/a |
The option is set when Bash is a login shell. This is a readonly option. The option is set when Bash is a login shell. This is a readonly option.
### mailwarn ### mailwarn
Option: `mailwarn` Since: unknown | Option: | `mailwarn` | Since: | unknown |
------------- ----------------- ---------- --------- |:------------|:----------------|:---------|:--------|
Shell mode: interactive (?) Default: off | Shell mode: | interactive (?) | Default: | off |
If set, and a file that Bash is checking for mail has been accessed If set, and a file that Bash is checking for mail has been accessed
since the last time it was checked, the message \"The mail in mailfile since the last time it was checked, the message "The mail in mailfile
has been read\" is displayed. has been read" is displayed.
### no_empty_cmd_completion ### no_empty_cmd_completion
Option: `mailwarn` Since: unknown | Option: | `mailwarn` | Since: | unknown |
------------- ----------------- ---------- --------- |:------------|:----------------|:---------|:--------|
Shell mode: interactive (?) Default: off | Shell mode: | interactive (?) | Default: | off |
If set, and readline is being used, Bash will not attempt to search the If set, and readline is being used, Bash will not attempt to search the
PATH for possible completions when completion is attempted on an empty PATH for possible completions when completion is attempted on an empty
@ -395,45 +394,45 @@ line.
### nocaseglob ### nocaseglob
Option: `nocaseglob` Since: 2.02-alpha1 | Option: | `nocaseglob` | Since: | 2.02-alpha1 |
------------- -------------- ---------- ------------- |:------------|:-------------|:---------|:------------|
Shell mode: all Default: off | Shell mode: | all | Default: | off |
If set, Bash matches filenames in a case-insensitive fashion when If set, Bash matches filenames in a case-insensitive fashion when
performing pathname expansion. performing pathname expansion.
### nocasematch ### nocasematch
Option: `nocasematch` Since: 3.1-alpha1 | Option: | `nocasematch` | Since: | 3.1-alpha1 |
------------- --------------- ---------- ------------ |:------------|:--------------|:---------|:-----------|
Shell mode: all Default: off | Shell mode: | all | Default: | off |
If set, Bash matches patterns in a case-insensitive fashion when If set, Bash matches patterns in a case-insensitive fashion when
performing matching while executing `case` or `[[` conditional commands. performing matching while executing `case` or `[[` conditional commands.
### nullglob ### nullglob
Option: `nullglob` Since: unknown | Option: | `nullglob` | Since: | unknown |
------------- ------------ ---------- --------- |:------------|:-----------|:---------|:--------|
Shell mode: all Default: off | Shell mode: | all | Default: | off |
If set, Bash allows patterns which match no files to expand to a null If set, Bash allows patterns which match no files to expand to a null
string, rather than themselves. string, rather than themselves.
### progcomp ### progcomp
Option: `progcomp` Since: 2.04-alpha1 |Option:|`progcomp`|Since:|2.04-alpha1|
------------- ----------------- ---------- ------------- |-------|----------|------|----------|
Shell mode: interactive (?) Default: on |Shell mode:|interactive (?)|Default:|on|
If set, the programmable completion facilities are enabled. This option If set, the programmable completion facilities are enabled. This option
is enabled by default. is enabled by default.
### promptvars ### promptvars
Option: `promptvars` Since: unknown |Option:|`promptvars`|Since:|unknown|
------------- -------------- ---------- --------- |-------|------------|------|-------|
Shell mode: interactive Default: on |Shell mode:|interactive|Default:|on|
If set, prompt strings undergo parameter expansion, command If set, prompt strings undergo parameter expansion, command
substitution, arithmetic expansion, and quote removal after being substitution, arithmetic expansion, and quote removal after being
@ -442,27 +441,27 @@ default.
### restricted_shell ### restricted_shell
Option: `restricted_shell` Since: 2.03-alpha |Option:|`restricted_shell`|Since:|2.03-alpha|
------------- -------------------- ---------- ------------ |-------|------------------|------|-------|
Shell mode: interactive (?) Default: off |Shell mode:|interactive (?)|Default:|off|
The option is set when Bash is a restricted shell. This is a readonly The option is set when Bash is a restricted shell. This is a readonly
option. option.
### shift_verbose ### shift_verbose
Option: `shift_verbose` Since: unknown |Option:|`shift_verbose`|Since:|unknown|
------------- ----------------- ---------- ----------------------- |-------|---------------|------|-------|
Shell mode: all Default: off, on in POSIX mode |Shell mode:|all|Default:|off, on in POSIX mode|
If set, the shift builtin prints an error message when the shift count If set, the shift builtin prints an error message when the shift count
exceeds the number of positional parameters. exceeds the number of positional parameters.
### sourcepath ### sourcepath
Option: `sourcepath` Since: unknown |Option:|`sourcepath`|Since:|unknown|
------------- -------------- ---------- --------- |-------|------------|------|-------|
Shell mode: all Default: on |Shell mode:|all|Default:|on|
If set, the source builtin command uses the value of PATH to find the If set, the source builtin command uses the value of PATH to find the
directory containing the file supplied as an argument. This option is directory containing the file supplied as an argument. This option is
@ -470,9 +469,9 @@ enabled by default.
### syslog_history ### syslog_history
Option: `syslog_history` Since: 5.0-alpha |Option:|`syslog_history`|Since:|5.0-alpha|
------------- ------------------ ---------- ----------- |-------|----------------|------|--------|
Shell mode: unknown Default: off |Shell mode:|unknown|Default:|off|
If set, the shell history is sent to syslog. If set, the shell history is sent to syslog.
@ -481,9 +480,9 @@ syslog.
### xpg_echo ### xpg_echo
Option: `xpg_echo` Since: 2.04-beta1 |Option:|`xpg_echo`|Since:|2.04-beta1|
------------- ------------ ---------- ------------ |-------|----------|------|----------|
Shell mode: all Default: off |Shell mode:|all|Default:|off|
If set, the `echo`-builtin command expands backslash-escape sequences by If set, the `echo`-builtin command expands backslash-escape sequences by
default (POSIX, SUS, XPG). default (POSIX, SUS, XPG).

View File

@ -5,48 +5,48 @@ in mind that this version is a snapshot, the bashphorisms are changed
here and there. Also, [another here and there. Also, [another
snapshot](http://mywiki.wooledge.org/BashFAQ/064). snapshot](http://mywiki.wooledge.org/BashFAQ/064).
I think `greycat` was the first one who had the idea, but I\'m not sure. I think `greycat` was the first one who had the idea, but I'm not sure.
Our bashphorisms can be queried from `greybot` using `!bN`, where `N` is Our bashphorisms can be queried from `greybot` using `!bN`, where `N` is
the bashphorism number. the bashphorism number.
And yes, these bashphorisms reflect the daily reality in `#bash`. And yes, these bashphorisms reflect the daily reality in `#bash`.
Number Bashphorism |Number|Bashphorism|
-------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |------|-----------|
0 The questioner will never tell you what they are really doing the first time they ask. |0|The questioner will never tell you what they are really doing the first time they ask.|
1 The questioner's first description of the problem/question will be misleading. |1|The questioner's first description of the problem/question will be misleading.|
2 The questioner will keep changing the question until it drives the helpers in the channel insane. |2|The questioner will keep changing the question until it drives the helpers in the channel insane.|
3 Offtopicness will continue until someone asks a bash question that falls under bashphorisms 1 and/or 2, and `greycat` gets pissed off. |3|Offtopicness will continue until someone asks a bash question that falls under bashphorisms 1 and/or 2, and `greycat` gets pissed off.|
4 The questioner will not read and apply the answers he is given but will instead continue to practice bashphorism #1 and bashphorism #2. |4|The questioner will not read and apply the answers he is given but will instead continue to practice bashphorism #1 and bashphorism #2.|
5 The ignorant will continually mis-educate the other noobies. |5|The ignorant will continually mis-educate the other noobies.|
6 When given a choice of solutions, the newbie will always choose the wrong one. |6|When given a choice of solutions, the newbie will always choose the wrong one.|
7 The newbie will always find a reason to say, \"It doesn't work.\" |7|The newbie will always find a reason to say, "It doesn't work."|
8 If you don't know to whom the bashphorism's referring, it's you. |8|If you don't know to whom the bashphorism's referring, it's you.|
9 All examples given by the questioner will be broken, misleading, wrong, and not representative of the actual question. |9|All examples given by the questioner will be broken, misleading, wrong, and not representative of the actual question.|
10 See B1 |10|See B1|
11 Please apply `(( % 10 ))` to the bashphorism value. |11|Please apply `(( % 10 ))` to the bashphorism value.|
12 All logic is deniable; however, some logic will \*plonk\* you if you deny it. |12|All logic is deniable; however, some logic will *plonk* you if you deny it.|
13 Everyone ignores greycat when he is right. When he is wrong, it is !b1 |13|Everyone ignores greycat when he is right. When he is wrong, it is !b1|
14 The newbie doesn't actually know what he's asking. If he did, he wouldn't need to ask. |14|The newbie doesn't actually know what he's asking. If he did, he wouldn't need to ask.|
15 The more advanced you are, the more likely you are to be overcomplicating it. |15|The more advanced you are, the more likely you are to be overcomplicating it.|
16 The more beginner you are, the more likely you are to be overcomplicating it. |16|The more beginner you are, the more likely you are to be overcomplicating it.|
17 A newbie comes to #bash to get his script confirmed. He leaves disappointed. |17|A newbie comes to #bash to get his script confirmed. He leaves disappointed.|
18 The newbie will not accept the answer you give, no matter how right it is. |18|The newbie will not accept the answer you give, no matter how right it is.|
19 The newbie is a bloody loon. |19|The newbie is a bloody loon.|
20 The newbie will always have some excuse for doing it wrong. |20|The newbie will always have some excuse for doing it wrong.|
21 When the newbie's question is ambiguous, the proper interpretation will be whichever one makes the problem the hardest to solve. |21|When the newbie's question is ambiguous, the proper interpretation will be whichever one makes the problem the hardest to solve.|
22 The newcomer will abuse the bot's factoid triggers for their own entertainment until someone gets annoyed enough to ask them to message it privately instead. |22|The newcomer will abuse the bot's factoid triggers for their own entertainment until someone gets annoyed enough to ask them to message it privately instead.|
23 Everyone is a newcomer. |23|Everyone is a newcomer.|
24 The newcomer will address greybot as if it were human. |24|The newcomer will address greybot as if it were human.|
25 The newbie won't accept any answer that uses practical or standard tools. |25|The newbie won't accept any answer that uses practical or standard tools.|
26 The newbie will not TELL you about this restriction until you have wasted half an hour. |26|The newbie will not TELL you about this restriction until you have wasted half an hour.|
27 The newbie will lie. |27|The newbie will lie.|
28 When the full horror of the newbie's true goal is revealed, the newbie will try to restate the goal to trick you into answering. Newbies are stupid. |28|When the full horror of the newbie's true goal is revealed, the newbie will try to restate the goal to trick you into answering. Newbies are stupid.|
29 It's always git. Or python virtualenv. Or docker. One of those pieces of shit. ALWAYS. |29|It's always git. Or python virtualenv. Or docker. One of those pieces of shit. ALWAYS.|
30 They won't show you the homework assignment. That would make it too easy. |30|They won't show you the homework assignment. That would make it too easy.|
31 Your teacher is a f\*\*king idiot. |31|Your teacher is a f**king idiot.|
32 The more horrifyingly wrong a proposed solution is, the more likely it will be used. |32|The more horrifyingly wrong a proposed solution is, the more likely it will be used.|
33 The newbie cannot explain what he is doing, or why. He will show you incomprehensible, nonworking code instead. What? You can't read his mind?! |33|The newbie cannot explain what he is doing, or why. He will show you incomprehensible, nonworking code instead. What? You can't read his mind?!|
Please feel free to correct or extend this page whenever needed. Please feel free to correct or extend this page whenever needed.

View File

@ -12,13 +12,14 @@ tags:
# Bash's behaviour # Bash's behaviour
FIXME incomplete !!! warning "FIXME"
incomplete
## Bash startup modes ## Bash startup modes
### Login shell ### Login shell
As a \"login shell\", Bash reads and sets (executes) the user's profile As a "login shell", Bash reads and sets (executes) the user's profile
from `/etc/profile` and one of `~/.bash_profile`, `~/.bash_login`, or from `/etc/profile` and one of `~/.bash_profile`, `~/.bash_login`, or
`~/.profile` (in that order, using the first one that's readable!). `~/.profile` (in that order, using the first one that's readable!).
@ -27,20 +28,20 @@ When a login shell exits, Bash reads and executes commands from the file
Why an extra login shell mode? There are many actions and variable sets Why an extra login shell mode? There are many actions and variable sets
that only make sense for the initial user login. That's why all UNIX(r) that only make sense for the initial user login. That's why all UNIX(r)
shells have (should have) a \"login\" mode. shells have (should have) a "login" mode.
[**Methods to start Bash as a login shell:**]{.underline} <u>**Methods to start Bash as a login shell:**</u>
- the first character of `argv[0]` is `-` (a hyphen): traditional - the first character of `argv[0]` is `-` (a hyphen): traditional
UNIX(r) shells start from the `login` binary UNIX(r) shells start from the `login` binary
- Bash is started with the `-l` option - Bash is started with the `-l` option
- Bash is started with the `--login` option - Bash is started with the `--login` option
[**Methods to test for login shell mode:**]{.underline} <u>**Methods to test for login shell mode:**</u>
- the shell option `login_shell` is set - the shell option `login_shell` is set
[**Related switches:**]{.underline} <u>**Related switches:**</u>
- `--noprofile` disables reading of all profile files - `--noprofile` disables reading of all profile files
@ -49,7 +50,7 @@ shells have (should have) a \"login\" mode.
When Bash starts as an interactive non-login shell, it reads and When Bash starts as an interactive non-login shell, it reads and
executes commands from `~/.bashrc`. This file should contain, for executes commands from `~/.bashrc`. This file should contain, for
example, aliases, since they need to be defined in every shell as example, aliases, since they need to be defined in every shell as
they\'re not inherited from the parent shell. they're not inherited from the parent shell.
The feature to have a system-wide `/etc/bash.bashrc` or a similar The feature to have a system-wide `/etc/bash.bashrc` or a similar
system-wide rc-file is specific to vendors and distributors that ship system-wide rc-file is specific to vendors and distributors that ship
@ -57,11 +58,11 @@ system-wide rc-file is specific to vendors and distributors that ship
system-wide rc file is to `source /etc/bashrc` from every user's system-wide rc file is to `source /etc/bashrc` from every user's
`~/.bashrc`. `~/.bashrc`.
[**Methods to test for interactive-shell mode:**]{.underline} <u>**Methods to test for interactive-shell mode:**</u>
- the special parameter `$-` contains the letter `i` (lowercase I) - the special parameter `$-` contains the letter `i` (lowercase I)
[**Related switches:**]{.underline} <u>**Related switches:**</u>
- `-i` forces the interactive mode - `-i` forces the interactive mode
- `--norc` disables reading of the startup files (e.g. - `--norc` disables reading of the startup files (e.g.
@ -83,7 +84,7 @@ used as the name of the startup file.
After the startup files are read, Bash enters the [POSIX(r) compatiblity After the startup files are read, Bash enters the [POSIX(r) compatiblity
mode (for running, not for starting!)](#posix_run_mode). mode (for running, not for starting!)](#posix_run_mode).
[**Bash starts in `sh` compatiblity mode when:**]{.underline} <u>**Bash starts in `sh` compatiblity mode when:**</u>
- the base filename in `argv[0]` is `sh` (:!: NB: `/bin/sh` may be - the base filename in `argv[0]` is `sh` (:!: NB: `/bin/sh` may be
linked to `/bin/bash`, but that doesn't mean it acts like linked to `/bin/bash`, but that doesn't mean it acts like
@ -94,11 +95,11 @@ mode (for running, not for starting!)](#posix_run_mode).
When Bash is started in POSIX(r) mode, it follows the POSIX(r) standard When Bash is started in POSIX(r) mode, it follows the POSIX(r) standard
for startup files. In this mode, **interactive shells** expand the for startup files. In this mode, **interactive shells** expand the
[ENV](../syntax/shellvars.md#ENV) variable and commands are read and executed [ENV](../syntax/shellvars.md#ENV) variable and commands are read and executed
from the file whose name is the expanded value.\ from the file whose name is the expanded value.
No other startup files are read. Hence, a non-interactive shell doesn't No other startup files are read. Hence, a non-interactive shell doesn't
read any startup files in POSIX(r) mode. read any startup files in POSIX(r) mode.
[**Bash starts in POSIX(r) mode when:**]{.underline} <u>**Bash starts in POSIX(r) mode when:**</u>
- the commandline option `--posix` is specified - the commandline option `--posix` is specified
- the environment variable - the environment variable
@ -112,13 +113,13 @@ read any startup files in POSIX(r) mode.
Bash usually reads the first file found, when multiple choices are Bash usually reads the first file found, when multiple choices are
given (for user files in `~/`) given (for user files in `~/`)
Mode `/etc/profile` `~/.bash_profile` `~/.bash_login` `~/.profile` `~/.bashrc` `${ENV}` |Mode|`/etc/profile`|`~/.bash_profile`|`~/.bash_login`|`~/.profile`|`~/.bashrc`|`${ENV}`|
----------------------- ---------------- ------------------- ----------------- -------------- ------------- ---------- |--|--|--|--|--|--|--|
Login shell X X X X - - |Login shell|✅|✅|✅|✅|🚫|🚫|
Interactive shell - - - - X - |Interactive shell|🚫|🚫|🚫|🚫|✅|🚫|
SH compatible login X - - X - - |SH compatible login|✅|🚫|🚫|✅|🚫|🚫|
SH compatible - - - - - X |SH compatible|🚫|🚫|🚫|🚫|🚫|✅|
POSIX(r) compatiblity - - - - - X |POSIX(r) compatiblity|🚫|🚫|🚫|🚫|🚫|✅|
## Bash run modes ## Bash run modes
@ -304,9 +305,10 @@ and parsing (excerpt from a Bash maintainer's document):
Bash can be configured to be POSIX-conformant by default, by specifying Bash can be configured to be POSIX-conformant by default, by specifying
the `--enable-strict-posix-default' to `configure' when building. the `--enable-strict-posix-default' to `configure' when building.
FIXME help me to find out what breaks in POSIX(r) mode! !!! warning "FIXME"
help me to find out what breaks in POSIX(r) mode!
[**The POSIX(r) mode can be switched on by:**]{.underline} <u>**The POSIX(r) mode can be switched on by:**</u>
- Bash starting as `sh` (the basename of `argv[0]` is `sh`) - Bash starting as `sh` (the basename of `argv[0]` is `sh`)
- starting Bash with the commandline option `--posix` - starting Bash with the commandline option `--posix`
@ -314,7 +316,7 @@ FIXME help me to find out what breaks in POSIX(r) mode!
[POSIXLY_CORRECT](../syntax/shellvars.md#POSIXLY_CORRECT) is set [POSIXLY_CORRECT](../syntax/shellvars.md#POSIXLY_CORRECT) is set
- the command `set -o posix` - the command `set -o posix`
[**Tests for the POSIX(r) mode:**]{.underline} <u>**Tests for the POSIX(r) mode:**</u>
- the variable [SHELLOPTS](../syntax/shellvars.md#SHELLOPTS) contains - the variable [SHELLOPTS](../syntax/shellvars.md#SHELLOPTS) contains
`posix` in its list `posix` in its list
@ -330,7 +332,7 @@ like normal Bash with the following restrictions:
[PATH](../syntax/shellvars.md#PATH), [ENV](../syntax/shellvars.md#ENV) and [PATH](../syntax/shellvars.md#PATH), [ENV](../syntax/shellvars.md#ENV) and
[BASH_ENV](../syntax/shellvars.md#BASH_ENV) can't be set or unset [BASH_ENV](../syntax/shellvars.md#BASH_ENV) can't be set or unset
- command names that contain a `/` (slash) can't be called (hence - command names that contain a `/` (slash) can't be called (hence
you\'re limited to `PATH`) you're limited to `PATH`)
- filenames containing a `/` (slash) can't be specified as argument - filenames containing a `/` (slash) can't be specified as argument
to the `source` or `.` builtin command to the `source` or `.` builtin command
- filenames containing a `/` (slash) can't be specified as argument - filenames containing a `/` (slash) can't be specified as argument
@ -351,19 +353,19 @@ like normal Bash with the following restrictions:
- turning off restricted mode with `set +r` or `set +o restricted` is - turning off restricted mode with `set +r` or `set +o restricted` is
(of course) forbidden (of course) forbidden
The \"-r\" restrictions are turned on **after** Bash has read its The "-r" restrictions are turned on **after** Bash has read its
startup files. startup files.
When the command that is run is a shell script, then the restrictions When the command that is run is a shell script, then the restrictions
are **turned off** for the (sub-)shell that runs that shell script. are **turned off** for the (sub-)shell that runs that shell script.
[**The restricted shell can be switched on by:**]{.underline} <u>**The restricted shell can be switched on by:**</u>
- calling Bash as `rbash` (the basename of `argv[0]` is `rbash`) - calling Bash as `rbash` (the basename of `argv[0]` is `rbash`)
- calling Bash with the `-r` option - calling Bash with the `-r` option
- calling Bash with the `--restricted` option - calling Bash with the `--restricted` option
[**Tests for restricted mode:**]{.underline} <u>**Tests for restricted mode:**</u>
- the special parameter `$-` contains the letter `r` (lowercase R) - the special parameter `$-` contains the letter `r` (lowercase R)
- the shell option `restricted_shell` is set and can be checked by the - the shell option `restricted_shell` is set and can be checked by the

View File

@ -22,56 +22,56 @@ For this topic, see also
- [shell_options](../internals/shell_options.md) - [shell_options](../internals/shell_options.md)
- [set](../commands/builtin/set.md) - [set](../commands/builtin/set.md)
Feature or change description Appeared in Bash version See also/remarks |Feature or change description|Appeared in Bash version|See also/remarks|
--------------------------------- -------------------------- --------------------------------------------------------------------------------- |--|--|--|
`posix` (for `set -o`) 1.14.0 |`posix` (for `set -o`)|1.14.0||
`hostcomplete` 2.0-alpha3 |`hostcomplete`|2.0-alpha3||
`expand_aliases` 2.0 |`expand_aliases`|2.0||
`huponexit` 2.02-alpha1 |`huponexit`|2.02-alpha1||
`nocaseglob` 2.02-alpha1 |`nocaseglob`|2.02-alpha1||
`extglob` 2.02-alpha1 together with extended globbing, KSH88 |`extglob`|2.02-alpha1|together with extended globbing, KSH88|
`restricted_shell` 2.03-alpha |`restricted_shell`|2.03-alpha||
`xpg_echo` 2.04-beta1 |`xpg_echo`|2.04-beta1||
`progcomp` 2.04-alpha1 |`progcomp`|2.04-alpha1||
`no_empty_command_completion` 2.04 |`no_empty_command_completion`|2.04||
`login_shell` 2.05a-alpha1 |`login_shell`|2.05a-alpha1||
`nolog` (for `set -o`) 2.05a |`nolog` (for `set -o`)|2.05a||
`gnu_errfmt` 3.0-alpha |`gnu_errfmt`|3.0-alpha||
`force_fignore` 3.0-alpha |`force_fignore`|3.0-alpha||
`failglob` 3.0-alpha |`failglob`|3.0-alpha||
`extquote` 3.0-alpha unsure -- verify! |`extquote`|3.0-alpha|unsure -- verify!|
`extdebug` 3.0-alpha |`extdebug`|3.0-alpha||
`pipefail` (for `set -o`) 3.0 |`pipefail` (for `set -o`)|3.0||
`functrace` (for `set -o`) 3.0 |`functrace` (for `set -o`)|3.0||
`errtrace` (for `set -o`) 3.0 |`errtrace` (for `set -o`)|3.0||
`nocasematch` 3.1-alpha1 |`nocasematch`|3.1-alpha1||
`dirspell` 4.0-alpha |`dirspell`|4.0-alpha||
`globstar` 4.0-alpha |`globstar`|4.0-alpha||
`checkjobs` 4.0-alpha |`checkjobs`|4.0-alpha||
`autocd` 4.0-alpha |`autocd`|4.0-alpha||
`set -e` effects more intuitive 4.0 not directly specified by POSIX, but in consensus with POSIX WG |`set -e` effects more intuitive|4.0|not directly specified by POSIX, but in consensus with POSIX WG|
`compat40` 4.1-beta |`compat40`|4.1-beta||
`lastpipe` 4.2-alpha only works with job control disabled |`lastpipe`|4.2-alpha|only works with job control disabled|
`compat41` 4.2-alpha |`compat41`|4.2-alpha||
`globasciiranges` 4.3-alpha enable \"character range globbing\" to always act as if in `C` locale |`globasciiranges`|4.3-alpha|enable "character range globbing" to always act as if in `C` locale|
`compat42` 4.3-alpha |`compat42`|4.3-alpha||
`compat43` 4.4-alpha |`compat43`|4.4-alpha||
`compat44` 5.0-alpha |`compat44`|5.0-alpha||
`localvar_inherit` 5.0-alpha local variables inherit preceeding scope values if they have the same name |`localvar_inherit`|5.0-alpha|local variables inherit preceeding scope values if they have the same name|
`syslog_history` 5.0-alpha send history lines to syslog (undocumented, default off) if syslog is supported |`syslog_history`|5.0-alpha|send history lines to syslog (undocumented, default off) if syslog is supported|
`assoc_expand_once` 5.0-alpha expand associative array subscripts only one |`assoc_expand_once`|5.0-alpha|expand associative array subscripts only one|
`globasciiranges` 5.0-beta New default: on (default may be configured at compile time) |`globasciiranges`|5.0-beta|New default: on (default may be configured at compile time)|
`localvar_inherit` 5.0-beta guard code against inheriting from an incompatible data type |`localvar_inherit`|5.0-beta|guard code against inheriting from an incompatible data type|
`checkwinsize` 5.0-beta2 New default: on |`checkwinsize`|5.0-beta2|New default: on|
`shift_verbose` 5.0-beta2 Default on when in POSIX mode |`shift_verbose`|5.0-beta2|Default on when in POSIX mode|
### General (all/many builtins) ### General (all/many builtins)
Feature or change description Appeared in Bash version See also/remarks |Feature or change description|Appeared in Bash version|See also/remarks|
----------------------------------------------------------------------- -------------------------- ----------------------------------------------------------------- |--|--|--|
generally return 2 on usage error 2.0 |generally return 2 on usage error|2.0||
generally accept `--` (end of options) 2.0 |generally accept `--` (end of options)|2.0||
(where applicable) implement a `-p` option to produce reusable output 2.0 `shopt` and `umask` builtins were fixed to support that in 2.02 |(where applicable) implement a `-p` option to produce reusable output|2.0|`shopt` and `umask` builtins were fixed to support that in 2.02|
### printf ### printf
@ -79,20 +79,20 @@ For this topic, see also
- [printf](../commands/builtin/printf.md) - [printf](../commands/builtin/printf.md)
Feature or change description Appeared in Bash version See also/remarks |Feature or change description|Appeared in Bash version|See also/remarks|
------------------------------------------------------------- -------------------------- -------------------------------------------------------- |--|--|--|
new `printf` command 2.02-alpha1 |new `printf` command|2.02-alpha1||
respects `0..` and `0x..` prefixed numbers 2.04-beta1 consistency with arithmetic |respects `0..` and `0x..` prefixed numbers|2.04-beta1|consistency with arithmetic|
POSIX(r) length specifiers `j`, `t` and `z` 2.05a-alpha1 ISO C99 |POSIX(r) length specifiers `j`, `t` and `z`|2.05a-alpha1|ISO C99|
POSIX(r) flag `'` 2.05a-alpha1 |POSIX(r) flag `'`|2.05a-alpha1||
conversion `a` and `A` 2.05a-rc1 if provided by the underlying printf(3) |conversion `a` and `A`|2.05a-rc1|if provided by the underlying printf(3)|
conversion `F` 2.05a-rc1 |conversion `F`|2.05a-rc1||
conversion `n` 2.05a-rc1 |conversion `n`|2.05a-rc1||
new option `-v` 3.1-alpha1 |new option `-v`|3.1-alpha1||
escape sequences `\"` and `\?` 3.0-beta1 |escape sequences `\"` and `\?`|3.0-beta1||
modified option `-v` to assign to individual array elements 4.1-alpha |modified option `-v` to assign to individual array elements|4.1-alpha||
conversion `(...)T` 4.2-alpha support stftime(3) date/time format; uses current time |conversion `(...)T`|4.2-alpha|support stftime(3) date/time format; uses current time|
`\uNNNN` and `\UNNNNNNNN` escape sequences 4.2-alpha for: `printf`, `echo -e`, `$'...'` |`\uNNNN` and `\UNNNNNNNN` escape sequences|4.2-alpha|for: `printf`, `echo -e`, `$'...'`|
### Conditional expressions and test command ### Conditional expressions and test command
@ -101,141 +101,141 @@ For this topic, see also
- [conditional_expression](../syntax/ccmd/conditional_expression.md) - [conditional_expression](../syntax/ccmd/conditional_expression.md)
- [classictest](../commands/classictest.md) - [classictest](../commands/classictest.md)
Feature or change description Appeared in Bash version See also/remarks |Feature or change description|Appeared in Bash version|See also/remarks|
-------------------------------------------------------------------- -------------------------- -------------------------------------------------------------------------------------- |--|--|--|
`test`: `-o`, `==`, `<` and `>` 2.0 |`test`: `-o`, `==`, `<` and `>`|2.0||
`test`: `-N` 2.02 |`test`: `-N`|2.02||
`[[...]]`: new 2.02-alpha1 KSH93 |`[[...]]`: new|2.02-alpha1|KSH93|
`[[...]]`: regex support (`=~`) 3.0-alpha |`[[...]]`: regex support (`=~`)|3.0-alpha||
`[[...]]`: quotable right-hand-side of `=~` forces string matching 3.2-alpha for consistency with pattern matching |`[[...]]`: quotable right-hand-side of `=~` forces string matching|3.2-alpha|for consistency with pattern matching|
`[[...]]`: `<` and `>` operators respect locale 4.1-alpha for consistency, since 4.1-beta: ensure you have set compatiblity to >4.0 (default) |`[[...]]`: `<` and `>` operators respect locale|4.1-alpha|for consistency, since 4.1-beta: ensure you have set compatiblity to \>4.0 (default)|
`test`/`[`/`[[`: `-v` 4.2-alpha check if a variable is set |`test`/`[`/`[[`: `-v`|4.2-alpha|check if a variable is set|
`test`/`[`/`[[`: `-v` 4.2-alpha support array syntax to check for elements |`test`/`[`/`[[`: `-v`|4.2-alpha|support array syntax to check for elements|
`test`/`[`/`[[`: `-N` accepts nanoseconds 5.1-alpha |`test`/`[`/`[[`: `-N` accepts nanoseconds|5.1-alpha||
`test`/`[`/`[[`: `-v` accepts positional parameters 5.1-alpha |`test`/`[`/`[[`: `-v` accepts positional parameters|5.1-alpha||
### Other builtins and keywords ### Other builtins and keywords
Builtin Feature or change description Appeared in Bash version See also/remarks |Builtin|Feature or change description|Appeared in Bash version|See also/remarks|
----------------------- -------------------------------------------------------------------------------------------------------------------------------------------- -------------------------- ----------------------------------------------------------------------------------------------- |--|--|--|--|
`bashbug` new 1.14.0 |`bashbug`|new|1.14.0||
`select` new 1.14.0 |`select`|new|1.14.0||
`disown` new 2.0 |`disown`|new|2.0||
`shopt` new 2.0 [shopt](../commands/builtin/shopt.md) |`shopt`|new|2.0|[shopt](../commands/builtin/shopt.md)|
`declare` new options `-a` and `-F` 2.0 |`declare`|new options `-a` and `-F`|2.0||
`enable` builtin has basic plugin support (dlopen) 2.0 |`enable`|builtin has basic plugin support (dlopen)|2.0||
`exec` options `-l`, `-c` and `-a` 2.0 |`exec`|options `-l`, `-c` and `-a`|2.0||
`read` options `-p`, `-e` and `-a` 2.0 [read](../commands/builtin/read.md) |`read`|options `-p`, `-e` and `-a`|2.0|[read](../commands/builtin/read.md)|
`readonly` option `-a` 2.0 [arrays](../syntax/arrays.md) |`readonly`|option `-a`|2.0|[arrays](../syntax/arrays.md)|
`time` new keyword 2.0 |`time`|new keyword|2.0||
`shopt` `-p` (reusable output) 2.02 |`shopt`|`-p` (reusable output)|2.02||
`umask` `-p` (reusable output) 2.02 |`umask`|`-p` (reusable output)|2.02||
`complete` new 2.04-devel for and together with support for programmable completion |`complete`|new|2.04-devel|for and together with support for programmable completion|
`compgen` new 2.04-devel for and together with support for programmable completion |`compgen`|new|2.04-devel|for and together with support for programmable completion|
`read` options `-t`, `-n`, `-d`, `-s` 2.04-devel [read](../commands/builtin/read.md) |`read`|options `-t`, `-n`, `-d`, `-s`|2.04-devel|[read](../commands/builtin/read.md)|
`for ((...;...;...))` new 2.04-devel KSH93 |`for ((...;...;...))`|new|2.04-devel|KSH93|
`set` print shell functions in a format reusable as input 2.05-beta1 |`set`|print shell functions in a format reusable as input|2.05-beta1||
`for` allow an empty word list 2.05a-alpha1 |`for`|allow an empty word list|2.05a-alpha1||
`read` new option `-u` 2.05b-alpha1 [read](../commands/builtin/read.md) |`read`|new option `-u`|2.05b-alpha1|[read](../commands/builtin/read.md)|
`caller` new 3.0 [caller](../commands/builtin/caller.md) |`caller`|new|3.0|[caller](../commands/builtin/caller.md)|
`coproc` new 4.0-alpha |`coproc`|new|4.0-alpha||
`declare` new options `-l` and `-u` 4.0-alpha together with case-changing expansion forms |`declare`|new options `-l` and `-u`|4.0-alpha|together with case-changing expansion forms|
`case` new action list terminators \'\';;& and \'\';& 4.0-alpha ksh93: only `;&`. zsh and mksh: `;|`. mksh: all 4, (`;;&` is undocumented Bash compatibility) |`case`|new action list terminators '';;& and '';&|4.0-alpha|ksh93: only `;&`. zsh and mksh: `;|`. mksh: all 4, (`;;&` is undocumented Bash compatibility)|
`read` changed `-t` (fractional seconds) 4.0-alpha |`read`|changed `-t` (fractional seconds)|4.0-alpha||
`mapfile` new 4.0-alpha |`mapfile`|new|4.0-alpha||
`read` new option `-i` 4.0-alpha |`read`|new option `-i`|4.0-alpha||
`compopt` new 4.0-alpha |`compopt`|new|4.0-alpha||
`read` modified option `-t` to test for data 4.0-beta |`read`|modified option `-t` to test for data|4.0-beta||
`read` new option `-N` 4.1-alpha |`read`|new option `-N`|4.1-alpha||
`mapfile` changed behaviour regarding history spamming 4.1-alpha |`mapfile`|changed behaviour regarding history spamming|4.1-alpha||
`declare` new option `-g` 4.2-alpha |`declare`|new option `-g`|4.2-alpha||
`mapfile` calls the callback with an additional argument: The line (data) 4.2-alpha |`mapfile`|calls the callback with an additional argument: The line (data)|4.2-alpha||
`cd` new option `-e` 4.2-alpha |`cd`|new option `-e`|4.2-alpha||
`echo` `\uNNNN` and `\UNNNNNNNN` escape sequences 4.2-alpha for: `printf`, `echo -e`, `$'...'` |`echo`|`\uNNNN` and `\UNNNNNNNN` escape sequences|4.2-alpha|for: `printf`, `echo -e`, `$'...'`|
`exec` option `-a` to give a `argv[0]` string 4.2-alpha |`exec`|option `-a` to give a `argv[0]` string|4.2-alpha||
`time` allowed as a command by itself to display timing values of the shell and its children 4.2-alpha POSIX change |`time`|allowed as a command by itself to display timing values of the shell and its children|4.2-alpha|POSIX change|
`help` `help` now searches exact topic-strings (i.e. `help read` won't find `readonly` anymore) 4.3-alpha |`help`|`help` now searches exact topic-strings (i.e. `help read` won't find `readonly` anymore)|4.3-alpha||
`return` accept negative values as return value (e.g. `return -1` will show as (8 bit) 255 in the caller) 4.3-alpha |`return`|accept negative values as return value (e.g. `return -1` will show as (8 bit) 255 in the caller)|4.3-alpha||
`exit` accept negative values as return value (e.g. `return -1` will show as (8 bit) 255 in the caller) 4.3-alpha |`exit`|accept negative values as return value (e.g. `return -1` will show as (8 bit) 255 in the caller)|4.3-alpha||
`read` `read` skips `NUL` (ASCII Code 0) in input 4.3-alpha |`read`|`read` skips `NUL` (ASCII Code 0) in input|4.3-alpha||
`declare` new option `-n`/`+n` to support nameref variable type 4.3-alpha |`declare`|new option `-n`/`+n` to support nameref variable type|4.3-alpha||
`wait` new option `-n` to wait for the next background job to finish, returning its exit status. 4.3-alpha |`wait`|new option `-n` to wait for the next background job to finish, returning its exit status.|4.3-alpha||
`read` `read` checks first variable argument for validity before trying to read inout 4.3-beta |`read`|`read` checks first variable argument for validity before trying to read inout|4.3-beta||
`help` attempts substring matching (as it did through bash-4.2) if exact string matching fails 4.3-beta2 |`help`|attempts substring matching (as it did through bash-4.2) if exact string matching fails|4.3-beta2||
`fc` interprets option `-0` (zero) as the current command line 4.3-beta2 |`fc`|interprets option `-0` (zero) as the current command line|4.3-beta2||
`cd` new option `-@` to browse a file's extended attributes (on systems that support `O_XATTR`) 4.3-rc1 |`cd`|new option `-@` to browse a file's extended attributes (on systems that support `O_XATTR`)|4.3-rc1||
`kill` new option `-L` (upper case ell) to list signals like the normal lowercase option `-l` (compatiblity with some standalone `kill` commands) 4.4-beta |`kill`|new option `-L` (upper case ell) to list signals like the normal lowercase option `-l` (compatiblity with some standalone `kill` commands)|4.4-beta||
`mapfile` new option `-d` 4.4-alpha |`mapfile`|new option `-d`|4.4-alpha||
`wait` new option `-f` 5.0-alpha |`wait`|new option `-f`|5.0-alpha||
`history` option `-d` allows negative numbers to index from the end of the history list 5.0-alpha |`history`|option `-d` allows negative numbers to index from the end of the history list|5.0-alpha||
`umask` allows modes greater than octal 777 5.0-alpha |`umask`|allows modes greater than octal 777|5.0-alpha||
`times` honors current locale settings when printing decimal points 5.0-alpha |`times`|honors current locale settings when printing decimal points|5.0-alpha||
`kill` New options `-n SIGNUMBER` and `-s SIGNAME` 5.0-beta2 [kill](../commands/builtin/kill.md) |`kill`|New options `-n SIGNUMBER` and `-s SIGNAME`|5.0-beta2|[kill](/commands/builtin/kill)|
`select` Support for an empty wordlist following `in` 5.0-beta2 |`select`|Support for an empty wordlist following `in`|5.0-beta2||
`read` Option `-e` (use ReadLine to obtain input) now works with arbitrary file descriptors (given by `-u` option) 5.1-alpha |`read`|Option `-e` (use ReadLine to obtain input) now works with arbitrary file descriptors (given by `-u` option)|5.1-alpha||
`trap` `-p` option prints signals with SIG_DFL/SIG_IGN on shell start (POSIX mode) 5.1-alpha |`trap`|`-p` option prints signals with SIG_DFL/SIG_IGN on shell start (POSIX mode)|5.1-alpha||
`unset` automatically tries to unset a function if the given name is an invalid variable name 5.1-aplha |`unset`|automatically tries to unset a function if the given name is an invalid variable name|5.1-aplha||
`wait` option `-n` now accepts a list of jobs 5.1-alpha |`wait`|option `-n` now accepts a list of jobs|5.1-alpha||
`wait` new option `-p NAME` to store PID/JobID (useful when waiting for a list of jobs) 5.1-alpha |`wait`|new option `-p NAME` to store PID/JobID (useful when waiting for a list of jobs)|5.1-alpha||
`local` new option `-p` to print local variables in the current scope 5.1-alpha |`local`|new option `-p` to print local variables in the current scope|5.1-alpha||
`ulimit` new option `-R` to get/set `RLIMIT_RTTIME` resource 5.1-alpha |`ulimit`|new option `-R` to get/set `RLIMIT_RTTIME` resource|5.1-alpha||
## Builtin variables ## Builtin variables
Feature or change description Appeared in Bash version See also |Feature or change description|Appeared in Bash version|See also|
--------------------------------------------------- -------------------------- ---------------------------------------------------------------------------------- |--|--|--|
`HISTCMD` 1.14.0 interactive usage |`HISTCMD`|1.14.0|interactive usage|
`PS1`, `PS2`, `PATH`, and `IFS` are unsettable 2.0 |`PS1`, `PS2`, `PATH`, and `IFS` are unsettable|2.0||
`DIRSTACK` array variable 2.0 |`DIRSTACK` array variable|2.0||
`PIPESTATUS` array variable 2.0 |`PIPESTATUS` array variable|2.0||
`BASH_VERSINFO` array variable 2.0 |`BASH_VERSINFO` array variable|2.0||
`HOSTNAME` 2.0 |`HOSTNAME`|2.0||
`SHELLOPTS` 2.0 |`SHELLOPTS`|2.0||
`MACHTYPE` 2.0 |`MACHTYPE`|2.0||
`GLOBIGNORE` 2.0 |`GLOBIGNORE`|2.0||
`HISTIGNORE` 2.0 |`HISTIGNORE`|2.0||
respect `LC_ALL` 2.0 |respect `LC_ALL`|2.0||
respect `LC_MESSAGES` 2.0 |respect `LC_MESSAGES`|2.0||
respect `LC_CTYPE` 2.0 |respect `LC_CTYPE`|2.0||
respect `LC_COLLATE` 2.0 |respect `LC_COLLATE`|2.0||
respect `LANG` 2.0 |respect `LANG`|2.0||
`GROUPS` array variable 2.01 |`GROUPS` array variable|2.01||
`GROUPS` unsettable/takes (discarded) assignments 2.04 |`GROUPS` unsettable/takes (discarded) assignments|2.04||
`FUNCNAME` 2.04 |`FUNCNAME`|2.04||
respect `LC_NUMERIC` 2.04 |respect `LC_NUMERIC`|2.04||
`TMOUT` 2.05b |`TMOUT`|2.05b||
`BASH_REMATCH` 3.0 together with regex support in `[[...]]` |`BASH_REMATCH`|3.0|together with regex support in `[[...]]`|
`BASH_ARGC` 3.0 debugger support |`BASH_ARGC`|3.0|debugger support|
`BASH_ARGV` 3.0 debugger support |`BASH_ARGV`|3.0|debugger support|
`BASH_SOURCE` 3.0 debugger support |`BASH_SOURCE`|3.0|debugger support|
`BASH_LINENO` 3.0 debugger support |`BASH_LINENO`|3.0|debugger support|
`BASH_SUBSHELL` 3.0 debugger support |`BASH_SUBSHELL`|3.0|debugger support|
`BASH_EXECUTION_STRING` 3.0 debugger support |`BASH_EXECUTION_STRING`|3.0|debugger support|
`BASH_COMMAND` 3.0 debugger support |`BASH_COMMAND`|3.0|debugger support|
`HISTTIMEFORMAT` 3.0 |`HISTTIMEFORMAT`|3.0||
`COMP_WORDBREAKS` 3.0 |`COMP_WORDBREAKS`|3.0||
respect `LC_TIME` 3.1 |respect `LC_TIME`|3.1||
`BASHPID` 4.0-alpha Added to mksh R41. |`BASHPID`|4.0-alpha|Added to mksh R41.|
`PROMPT_DIRTRIM` 4.0 |`PROMPT_DIRTRIM`|4.0||
`BASH_XTRACEFD` 4.1-alpha |`BASH_XTRACEFD`|4.1-alpha||
`BASHOPTS` 4.1-alpha |`BASHOPTS`|4.1-alpha||
`FUNCNEST` 4.2-alpha |`FUNCNEST`|4.2-alpha||
`HISTSIZE` 4.3-alpha can be set to negative values for unlimited history length |`HISTSIZE`|4.3-alpha|can be set to negative values for unlimited history length|
`HISTFILESIZE` 4.3-alpha can be set to negative values for unlimit history file size |`HISTFILESIZE`|4.3-alpha|can be set to negative values for unlimit history file size|
`CHILD_MAX` 4.3-alpha max. number of exit status of children the shell remembers |`CHILD_MAX`|4.3-alpha|max. number of exit status of children the shell remembers|
`BASH_COMPAT` 4.3-alpha set shell compatiblity levels |`BASH_COMPAT`|4.3-alpha|set shell compatiblity levels|
`EPOCHSECONDS` 5.0-alpha expands to the time in seconds since Unix epoch |`EPOCHSECONDS`|5.0-alpha|expands to the time in seconds since Unix epoch|
`EPOCHREALTIME` 5.0-alpha expands to the time in seconds since Unix epoch with microsecond granularity |`EPOCHREALTIME`|5.0-alpha|expands to the time in seconds since Unix epoch with microsecond granularity|
`BASH_ARGV0` 5.0-alpha get/set `$0` |`BASH_ARGV0`|5.0-alpha|get/set `$0`|
`PATH` 5.0-alpha Possibility to set a static path for use in a restricted shell (at compile time) |`PATH`|5.0-alpha|Possibility to set a static path for use in a restricted shell (at compile time)|
`HISTSIZE` 5.0-beta Default can now be set at runtime |`HISTSIZE`|5.0-beta|Default can now be set at runtime|
`SRANDOM` 5.1-alpha New random generator for 32bit numbers (using various methods in the backend) |`SRANDOM`|5.1-alpha|New random generator for 32bit numbers (using various methods in the backend)|
`ARGV0` 5.1-alpha Respected when set in initial shell environment, then initially used to set `$0` |`ARGV0`|5.1-alpha|Respected when set in initial shell environment, then initially used to set `$0`|
`BASH_REMATCH` 5.1-alpha Not readonly anymore |`BASH_REMATCH`|5.1-alpha|Not readonly anymore|
`PROMPT_COMMANDS` 5.1-alpha New array variable. List of commands to be executed like `PROMPT_COMMAND` |`PROMPT_COMMANDS`|5.1-alpha|New array variable. List of commands to be executed like `PROMPT_COMMAND`|
`SECONDS` 5.1-alpha Assignment using arithmetic expressions (is nominally an integer variabnle) |`SECONDS`|5.1-alpha|Assignment using arithmetic expressions (is nominally an integer variabnle)|
`RANDOM` 5.1-alpha Assignment using arithmetic expressions (is nominally an integer variabnle) |`RANDOM`|5.1-alpha|Assignment using arithmetic expressions (is nominally an integer variabnle)|
`LINENO` 5.1-alpha Not an integer variabe |`LINENO`|5.1-alpha|Not an integer variabe|
## Quoting, expansions, substitutions and related ## Quoting, expansions, substitutions and related
@ -243,40 +243,40 @@ For this topic, see also
- [pe](../syntax/pe.md). - [pe](../syntax/pe.md).
Feature or change description Appeared in Bash version Remarks |Feature or change description|Appeared in Bash version|Remarks|
------------------------------------------------------------------------------------------------------ -------------------------- --------------------------------------------------------------------------------------------------------------- |--|--|--|
Support for integer-indexed arrays 2.0 relevant builtins also got array support |Support for integer-indexed arrays|2.0|relevant builtins also got array support|
`${PARAMETER//PATTERN/REPLACEMENT}` 2.0 |`${PARAMETER//PATTERN/REPLACEMENT}`|2.0||
`${PARAMETER:OFFSET:LENGTH}` 2.0 |`${PARAMETER:OFFSET:LENGTH}`|2.0||
`${!PARAMETER}` (indirection) 2.0 |`${!PARAMETER}` (indirection)|2.0||
`$"..."` (localized strings) 2.0 |`$"..."` (localized strings)|2.0||
`$'...'` (ANSI-C-like strings) 2.0 |`$'...'` (ANSI-C-like strings)|2.0||
`\xNNN` in `$'...'` (and `echo -e`) 2.02-alpha1 |`\xNNN` in `$'...'` (and `echo -e`)|2.02-alpha1||
`$(< FILENAME)` (file content) 2.02-alpha1 |`$(< FILENAME)` (file content)|2.02-alpha1||
globbing (`fnmatch()`) capable of POSIX(r) character classes etc. 2.02-alpha1 |globbing (`fnmatch()`) capable of POSIX(r) character classes etc.|2.02-alpha1||
extended globbing 2.02-alpha1 KSH88 |extended globbing|2.02-alpha1|KSH88|
globbing inside array mass-assignment: `ARRAY=(*.txt)` 2.03-alpha |globbing inside array mass-assignment: `ARRAY=(*.txt)`|2.03-alpha||
`$'...\'...'` escaped single quote inside ANSI-C-like strings 2.04-devel KSH93 |`$'...\'...'` escaped single quote inside ANSI-C-like strings|2.04-devel|KSH93|
`${!PREFIX*}` (parameter name expansion) 2.04 KSH93 |`${!PREFIX*}` (parameter name expansion)|2.04|KSH93|
`$'...'` expands `\cx` (Control-x) 2.05b |`$'...'` expands `\cx` (Control-x)|2.05b||
`[:class:]` syntax for pattern matching 2.05b KSH93 |`[:class:]` syntax for pattern matching|2.05b|KSH93|
`${!ARRAY[@]}` (array index expansion) 3.0-alpha KSH93 |`${!ARRAY[@]}` (array index expansion)|3.0-alpha|KSH93|
`{x..y}` (range brace expansion) 3.0-alpha |`{x..y}` (range brace expansion)|3.0-alpha||
`$'...'` expands `\xNNN` (Hexdigits) 3.0 |`$'...'` expands `\xNNN` (Hexdigits)|3.0||
`+=` operator for arrays and strings 3.1-alpha1 |`+=` operator for arrays and strings|3.1-alpha1||
`${PARAMETER//PATTERN/REPLACEMENT}` behaviour changed 3.2-alpha anchoring for global substitution is no longer allowed, changes the way old syntax may work |`${PARAMETER//PATTERN/REPLACEMENT}` behaviour changed|3.2-alpha|anchoring for global substitution is no longer allowed, changes the way old syntax may work|
`${@:0:x}` includes `$0` 4.0-alpha |`${@:0:x}` includes `$0`|4.0-alpha||
Support for associative arrays 4.0-alpha relevant builtins also got associative array support |Support for associative arrays|4.0-alpha|relevant builtins also got associative array support|
case modification operators for expansions 4.0-alpha |case modification operators for expansions|4.0-alpha||
`{0x..0y}` (zeropadding brace expansion) 4.0-alpha |`{0x..0y}` (zeropadding brace expansion)|4.0-alpha||
numerically indexed arrays can be accessed (on expansion time) from the end using negative indexes 4.1-alpha |numerically indexed arrays can be accessed (on expansion time) from the end using negative indexes|4.1-alpha||
`\uNNNN` and `\uNNNNNNNN` in `$'...'` 4.2-alpha for: `printf`, `echo -e`, `$'...'` |`\uNNNN` and `\uNNNNNNNN` in `$'...'`|4.2-alpha|for: `printf`, `echo -e`, `$'...'`|
`${PARAMETER:OFFSET:LENGTH}`: Negative `LENGTH` values are used as offset from the end of the string 4.2-alpha Substrings only for Bash and ksh93. Works also for argument expansions in zsh. ksh93 can use `${arr[n..-m]}`. |`${PARAMETER:OFFSET:LENGTH}`: Negative `LENGTH` values are used as offset from the end of the string|4.2-alpha|Substrings only for Bash and ksh93. Works also for argument expansions in zsh. ksh93 can use `${arr[n..-m]}`.|
Word expansions like `${foo##bar}` understand indirect variable references 4.3-beta |Word expansions like `${foo##bar}` understand indirect variable references|4.3-beta||
Transformations 4.4 |Transformations|4.4||
Process substitution now works in POSIX mode 5.1-alpha |Process substitution now works in POSIX mode|5.1-alpha||
New transformations: `U`, `u`, `L` 5.1-alpha Case-transformation |New transformations: `U`, `u`, `L`|5.1-alpha|Case-transformation|
New transformation: `K` 5.1-alpha Display associative arrays as key/value pairs |New transformation: `K`|5.1-alpha|Display associative arrays as key/value pairs|
## Arithmetic ## Arithmetic
@ -285,15 +285,15 @@ For this topic, see also
- [arith_expr](../syntax/arith_expr.md) - [arith_expr](../syntax/arith_expr.md)
- [arith](../syntax/expansion/arith.md) - [arith](../syntax/expansion/arith.md)
Feature or change description Appeared in Bash version Remarks |Feature or change description|Appeared in Bash version|Remarks|
-------------------------------------------- -------------------------- ------------------------------------------- |--|--|--|
`((...))` 2.0-beta2 KSH93 |`((...))`|2.0-beta2|KSH93|
ternary operator 2.0 |ternary operator|2.0||
base 64 integer constants 2.0 the max. base before is unknown. Anybody? |base 64 integer constants|2.0|the max. base before is unknown. Anybody?|
deprecated `$[...]` in favor of `$((...))` 2.0 |deprecated `$[...]` in favor of `$((...))`|2.0||
exponentiaition operator (`**`) 2.02-alpha1 |exponentiaition operator (`**`)|2.02-alpha1||
comma operator `EXPR,EXPR` 2.04-devel |comma operator `EXPR,EXPR`|2.04-devel||
pre- and postfix operators 2.04-devel |pre- and postfix operators|2.04-devel||
## Redirection and related ## Redirection and related
@ -301,33 +301,33 @@ For this topic, see also
- [redirection](../syntax/redirection.md) - [redirection](../syntax/redirection.md)
Feature or change description Appeared in Bash version Remarks |Feature or change description|Appeared in Bash version|Remarks|
--------------------------------------------------------------------------------------- -------------------------- --------- |--|--|--|
socket redirection (`/dev/tcp/`, `/dev/udp/`) 2.04-devel |socket redirection (`/dev/tcp/`, `/dev/udp/`)|2.04-devel||
OS/filesystem-independent support for `/dev/std(in|out|err)` and `/dev/fd/*` 2.04 |OS/filesystem-independent support for `/dev/std(in|out|err)` and `/dev/fd/*`|2.04||
socket redirection accepts service names 2.05 |socket redirection accepts service names|2.05||
`[n]<&word-` and `[n]>&word-` FD-duplicate/closing 2.05b-alpha1 KSH93 |`[n]<&word-` and `[n]>&word-` FD-duplicate/closing|2.05b-alpha1|KSH93|
Here strings: `<<< WORD` 2.05b-alpha1 |Here strings: `<<< WORD`|2.05b-alpha1||
`|&` (synonym for `2>&1 |`) 4.0-alpha |`|&` (synonym for `2>&1|`)|4.0-alpha||
`&>>` (equiv. to `>>FILE 2>&1`) 4.0-alpha |`&>>` (equiv. to `>>FILE 2>&1`)|4.0-alpha||
`{varname}` style automatic file descriptor allocation 4.1-alpha ksh93 |`{varname}` style automatic file descriptor allocation|4.1-alpha|ksh93|
`{varname[idx]}` fd allocation accepts array subscripts and special-meaning variables 4.3-alpha ksh93 |`{varname[idx]}` fd allocation accepts array subscripts and special-meaning variables|4.3-alpha|ksh93|
## Misc ## Misc
Feature or change description Appeared in Bash version See also/remarks |Feature or change description|Appeared in Bash version|See also/remarks|
------------------------------------------------------------------------------------------------- -------------------------- ------------------------------------------------------------------------------------------------------------------------------------------ |--|--|--|
`DEBUG` trap 2.0 |`DEBUG` trap|2.0||
`ERR` trap 2.05a KSH93 |`ERR` trap|2.05a|KSH93|
Support for multibyte characters: Unicode / UTF8 2.05b |Support for multibyte characters: Unicode / UTF8|2.05b||
`RETURN` trap 3.0 ksh93 `EXIT` trap evaluates in caller scope (for `function name {`). Bash `RETURN` in same scope. |`RETURN` trap|3.0|ksh93 `EXIT` trap evaluates in caller scope (for `function name {`). Bash `RETURN` in same scope.|
`command_not_found_handle` handler function 4.0-alpha |`command_not_found_handle` handler function|4.0-alpha||
official introduction of switchable \"compatiblity levels\" 4.0-alpha `compat31` was introduced in a 3.2 version, mainly because of the incompatibilities that were introduced by the changed `=~` operator |official introduction of switchable "compatiblity levels"|4.0-alpha|`compat31` was introduced in a 3.2 version, mainly because of the incompatibilities that were introduced by the changed `=~` operator|
`[[...]]` and `((...))` conditional commands are subject to the `ERR` trap and `set -e` feature 4.1-alpha |`[[...]]` and `((...))` conditional commands are subject to the `ERR` trap and `set -e` feature|4.1-alpha||
ACL support for file status checks 4.1-alpha |ACL support for file status checks|4.1-alpha||
Assignment to negative array indices 4.3-alpha ksh93, zsh |Assignment to negative array indices|4.3-alpha|ksh93, zsh|
`declare`/`typeset -n` 4.3-alpha Support for nameref variable type, a variable referencing another one by name |`declare`/`typeset -n`|4.3-alpha|Support for nameref variable type, a variable referencing another one by name|
shells started to run process substitutions now run any trap set on `EXIT` 4.3-beta |shells started to run process substitutions now run any trap set on `EXIT`|4.3-beta||
process substitution does not inherit the `v` flag 5.0-alpha |process substitution does not inherit the `v` flag|5.0-alpha||
`ERR` trap 5.0-alpha Reports more reliable line numbers |`ERR` trap|5.0-alpha|Reports more reliable line numbers|
Variable assignment 5.0-beta Assignments preceeding a special builtin that chages variable attributes are not propagated back unless compatiblity mode is 44 or lower |Variable assignment|5.0-beta|Assignments preceeding a special builtin that chages variable attributes are not propagated back unless compatiblity mode is 44 or lower|

View File

@ -49,31 +49,31 @@ You can follow the process by using `echo` as a fake interpreter:
#!/bin/echo #!/bin/echo
We don't need a script body here, as the file will never be interpreted We don't need a script body here, as the file will never be interpreted
and executed by \"`echo`\". You can see what the Operating System does, and executed by "`echo`". You can see what the Operating System does,
it calls \"`/bin/echo`\" with the name of the executable file and it calls "`/bin/echo`" with the name of the executable file and
following arguments. following arguments.
$ /home/bash/bin/test testword hello $ /home/bash/bin/test testword hello
/home/bash/bin/test testword hello /home/bash/bin/test testword hello
The same way, with `#!/bin/bash` the shell \"`/bin/bash`\" is called The same way, with `#!/bin/bash` the shell "`/bin/bash`" is called
with the script filename as an argument. It's the same as executing with the script filename as an argument. It's the same as executing
\"`/bin/bash /home/bash/bin/test testword hello`\" "`/bin/bash /home/bash/bin/test testword hello`"
If the interpreter can be specified with arguments and how long it can If the interpreter can be specified with arguments and how long it can
be is system-specific (see be is system-specific (see
[#!-magic](http://www.in-ulm.de/~mascheck/various/shebang/)). When Bash [#!-magic](http://www.in-ulm.de/~mascheck/various/shebang/)). When Bash
executes a file with a #!/bin/bash shebang, the shebang itself is executes a file with a #!/bin/bash shebang, the shebang itself is
ignored, since the first character is a hashmark \"#\", which indicates ignored, since the first character is a hashmark "`#`", which indicates
a comment. The shebang is for the operating system, not for the shell. a comment. The shebang is for the operating system, not for the shell.
Programs that don't ignore such lines, may not work as shebang driven Programs that don't ignore such lines, may not work as shebang driven
interpreters. interpreters.
<WRAP center round important 60%> [**Attention:**]{.underline}When the <WRAP center round important 60%> <u>**Attention:**</u>When the
specified interpreter is unavailable or not executable (permissions), specified interpreter is unavailable or not executable (permissions),
you usually get a \"`bad interpreter`\" error message., If you get you usually get a "`bad interpreter`" error message., If you get
nothing and it fails, check the shebang. Older Bash versions will nothing and it fails, check the shebang. Older Bash versions will
respond with a \"`no such file or directory`\" error for a nonexistant respond with a "`no such file or directory`" error for a nonexistant
interpreter specified by the shebang. </WRAP> interpreter specified by the shebang. </WRAP>
**Additional note:** When you specify `#!/bin/sh` as shebang and that's **Additional note:** When you specify `#!/bin/sh` as shebang and that's
@ -85,7 +85,7 @@ A common method is to specify a shebang like
#!/usr/bin/env bash #!/usr/bin/env bash
\...which just moves the location of the potential problem to ...which just moves the location of the potential problem to
- the `env` utility must be located in /usr/bin/ - the `env` utility must be located in /usr/bin/
- the needed `bash` binary must be located in `PATH` - the needed `bash` binary must be located in `PATH`
@ -104,7 +104,7 @@ files*:
- **stdout**: standard output - **stdout**: standard output
- **stderr**: standard error output - **stderr**: standard error output
Usually, they\'re all connected to your terminal, stdin as input file Usually, they're all connected to your terminal, stdin as input file
(keyboard), stdout and stderr as output files (screen). When calling (keyboard), stdout and stderr as output files (screen). When calling
such a program, the invoking shell can change these filedescriptor such a program, the invoking shell can change these filedescriptor
connections away from the terminal to any other file (see redirection). connections away from the terminal to any other file (see redirection).
@ -179,8 +179,8 @@ else
fi fi
``` ```
A common decision making command is \"`test`\" or its equivalent A common decision making command is "`test`" or its equivalent
\"`[`\". But note that, when calling test with the name \"`[`\", the "`[`". But note that, when calling test with the name "`[`", the
square brackets are not part of the shell syntax, the left bracket square brackets are not part of the shell syntax, the left bracket
**is** the test command! **is** the test command!
@ -194,7 +194,7 @@ fi
Read more about [the test command](../commands/classictest.md) Read more about [the test command](../commands/classictest.md)
A common exit code check method uses the \"`||`\" or \"`&&`\" operators. A common exit code check method uses the "`||`" or "`&&`" operators.
This lets you execute a command based on whether or not the previous This lets you execute a command based on whether or not the previous
command completed successfully: command completed successfully:
@ -203,13 +203,13 @@ grep ^root: /etc/passwd >/dev/null || echo "root was not found - check the pub a
which vi && echo "Your favourite editor is installed." which vi && echo "Your favourite editor is installed."
``` ```
Please, when your script exits on errors, provide a \"FALSE\" exit code, Please, when your script exits on errors, provide a "`FALSE`" exit code,
so others can check the script execution. so others can check the script execution.
## Comments ## Comments
In a larger, or complex script, it's wise to comment the code. Comments In a larger, or complex script, it's wise to comment the code. Comments
can help with debugging or tests. Comments start with the \# character can help with debugging or tests. Comments start with the `#` character
(hashmark) and continue to the end of the line: (hashmark) and continue to the end of the line:
``` bash ``` bash
@ -226,7 +226,7 @@ All three syntactically correct.
### Block commenting ### Block commenting
To temporarily disable complete blocks of code you would normally have To temporarily disable complete blocks of code you would normally have
to prefix every line of that block with a \# (hashmark) to make it a to prefix every line of that block with a `#` (hashmark) to make it a
comment. There's a little trick, using the pseudo command `:` (colon) comment. There's a little trick, using the pseudo command `:` (colon)
and input redirection. The `:` does nothing, it's a pseudo command, so and input redirection. The `:` does nothing, it's a pseudo command, so
it does not care about standard input. In the following code example, it does not care about standard input. In the following code example,
@ -254,14 +254,14 @@ redirection (a here-document) - the pseudo command didn't care about
it, effectively, the entire block was ignored. it, effectively, the entire block was ignored.
The here-document-tag was quoted here **to avoid substitutions** in the The here-document-tag was quoted here **to avoid substitutions** in the
\"commented\" text! Check [redirection with "commented" text! Check [redirection with
here-documents](../syntax/redirection.md#tag_heredoc) for more here-documents](../syntax/redirection.md#tag_heredoc) for more
## Variable scope ## Variable scope
In Bash, the scope of user variables is generally *global*. That means, In Bash, the scope of user variables is generally *global*. That means,
it does **not** matter whether a variable is set in the \"main program\" it does **not** matter whether a variable is set in the "main program"
or in a \"function\", the variable is defined everywhere. or in a "function", the variable is defined everywhere.
Compare the following *equivalent* code snippets: Compare the following *equivalent* code snippets:
@ -280,10 +280,10 @@ echo $myvariable
``` ```
In both cases, the variable `myvariable` is set and accessible from In both cases, the variable `myvariable` is set and accessible from
everywhere in that script, both in functions and in the \"main everywhere in that script, both in functions and in the "main
program\". program".
**[Attention:]{.underline}** When you set variables in a child process, **<u>Attention:</u>** When you set variables in a child process,
for example a *subshell*, they will be set there, but you will **never** for example a *subshell*, they will be set there, but you will **never**
have access to them outside of that subshell. One way to create a have access to them outside of that subshell. One way to create a
subshell is the pipe. It's all mentioned in a small article about [Bash subshell is the pipe. It's all mentioned in a small article about [Bash
@ -359,7 +359,7 @@ export myvariable
``` ```
Remember that the *exported* variable is a **copy**. There is no Remember that the *exported* variable is a **copy**. There is no
provision to \"copy it back to the parent.\" See the article about [Bash provision to "copy it back to the parent." See the article about [Bash
in the process tree](../scripting/processtree.md)! in the process tree](../scripting/processtree.md)!
[^1]: under specific circumstances, also by the shell itself [^1]: under specific circumstances, also by the shell itself

View File

@ -16,16 +16,16 @@ but as hints and comments about debugging a Bash script.
## Use a unique name for your script ## Use a unique name for your script
Do **not** name your script `test`, for example! *Why?* `test` is the Do **not** name your script `test`, for example! *Why?* `test` is the
name of a UNIX(r)-command, and [most likely built into your name of a UNIX(r)-command, and <u>most likely built into your
shell]{.underline} (it's a built-in in Bash) - so you won't be able to shell</u> (it's a built-in in Bash) - so you won't be able to
run a script with the name `test` in a normal way. run a script with the name `test` in a normal way.
**Don't laugh!** This is a classic mistake :-) **Don't laugh!** This is a classic mistake :-)
## Read the error messages ## Read the error messages
Many people come into IRC and ask something like *\"Why does my script Many people come into IRC and ask something like *"Why does my script
fail? I get an error!\"*. And when you ask them what the error message fail? I get an error!"*. And when you ask them what the error message
is, they don't even know. Beautiful. is, they don't even know. Beautiful.
Reading and interpreting error messages is 50% of your job as debugger! Reading and interpreting error messages is 50% of your job as debugger!
@ -33,9 +33,9 @@ Error messages actually **mean** something. At the very least, they can
give you hints as to where to start debugging. **READ YOUR ERROR give you hints as to where to start debugging. **READ YOUR ERROR
MESSAGES!** MESSAGES!**
You may ask yourself why is this mentioned as debugging tip? Well, [you You may ask yourself why is this mentioned as debugging tip? Well, <u>you
would be surprised how many shell users ignore the text of error would be surprised how many shell users ignore the text of error
messages!]{.underline} When I find some time, I\'ll paste 2 or 3 IRC messages!</u> When I find some time, I'll paste 2 or 3 IRC
log-snips here, just to show you that annoying fact. log-snips here, just to show you that annoying fact.
## Use a good editor ## Use a good editor
@ -85,7 +85,7 @@ There are two useful debug outputs for that task (both are written to
- print commands to be executed to `stderr` as if they were read - print commands to be executed to `stderr` as if they were read
from input (script file or keyboard) from input (script file or keyboard)
- print everything **before** any ([substitution and - print everything **before** any ([substitution and
expansion](../syntax/expansion/intro.md), \...) is applied expansion](../syntax/expansion/intro.md), ...) is applied
- `set -x` mode (`set -o xtrace`) - `set -x` mode (`set -o xtrace`)
- print everything as if it were executed, after [substitution and - print everything as if it were executed, after [substitution and
expansion](../syntax/expansion/intro.md) is applied expansion](../syntax/expansion/intro.md) is applied
@ -98,7 +98,7 @@ There are two useful debug outputs for that task (both are written to
configurable file descriptor, rather than sdtout by setting the configurable file descriptor, rather than sdtout by setting the
[BASH_XTRACEFD](../syntax/shellvars.md#BASH_XTRACEFD) variable. [BASH_XTRACEFD](../syntax/shellvars.md#BASH_XTRACEFD) variable.
**[Hint:]{.underline}** These modes can be entered when calling Bash: **<u>Hint:</u>** These modes can be entered when calling Bash:
- from commandline: `bash -vx ./myscript` - from commandline: `bash -vx ./myscript`
- from shebang (OS dependant): `#!/bin/bash -vx` - from shebang (OS dependant): `#!/bin/bash -vx`
@ -116,9 +116,9 @@ That fails. Why? Let's see the `xtrace` output:
+ '[' bar baz = test ']' + '[' bar baz = test ']'
And now you see that it's (\"bar\" and \"baz\") recognized as two And now you see that it's ("bar" and "baz") recognized as two
separate words (which you would have realized if you READ THE ERROR separate words (which you would have realized if you READ THE ERROR
MESSAGES ;) ). Let's check it\... MESSAGES ;) ). Let's check it...
# next try # next try
[ "$foo" = test ] [ "$foo" = test ]
@ -146,7 +146,7 @@ function*:
+(somefile.bash:412): echo 'Hello world' +(somefile.bash:412): echo 'Hello world'
\...and like this when you trace code *inside a function*: ...and like this when you trace code *inside a function*:
+(somefile.bash:412): myfunc(): echo 'Hello world' +(somefile.bash:412): myfunc(): echo 'Hello world'
@ -236,14 +236,14 @@ command](../syntax/ccmd/intro.md):
- did you close your `{` with a `}`? - did you close your `{` with a `}`?
- did you close your `(` with a `)`? - did you close your `(` with a `)`?
**[Note:]{.underline}** It seems that here-documents (tested on versions <u>**Note:**</u> It seems that here-documents (tested on versions
`1.14.7`, `2.05b`, `3.1.17` and `4.0`) are correctly terminated when `1.14.7`, `2.05b`, `3.1.17` and `4.0`) are correctly terminated when
there is an EOF before the end-of-here-document tag (see there is an EOF before the end-of-here-document tag (see
[redirection](../syntax/redirection.md)). The reason is unknown, but it seems [redirection](../syntax/redirection.md)). The reason is unknown, but it seems
to be deliberate. Bash 4.0 added an extra message for this: to be deliberate. Bash 4.0 added an extra message for this:
`` warning: here-document at line <N> delimited by end-of-file (wanted `<MARKER>') `` `` warning: here-document at line <N> delimited by end-of-file (wanted `<MARKER>') ``
### Unexpected end of file while looking for matching \... ### Unexpected end of file while looking for matching ...
script.sh: line 50: unexpected EOF while looking for matching `"' script.sh: line 50: unexpected EOF while looking for matching `"'
script.sh: line 100: syntax error: unexpected end of file script.sh: line 100: syntax error: unexpected end of file
@ -266,13 +266,13 @@ example for `xtrace` output from above. External commands may display
such an error message though in our example, it was the **internal** such an error message though in our example, it was the **internal**
test-command that yielded the error. test-command that yielded the error.
### !\": event not found ### !": event not found
$ echo "Hello world!" $ echo "Hello world!"
bash: !": event not found bash: !": event not found
This is not an error per se. It happens in interactive shells, when the This is not an error per se. It happens in interactive shells, when the
C-Shell-styled history expansion (\"`!searchword`\") is enabled. This is C-Shell-styled history expansion ("`!searchword`") is enabled. This is
the default. Disable it like this: the default. Disable it like this:
set +H set +H
@ -317,8 +317,8 @@ CRs are a pain.
Some possible sources of CRs: Some possible sources of CRs:
- a DOS/Windows text editor - a DOS/Windows text editor
- a UNIX(r) text editor that is \"too smart\" when determining the - a UNIX(r) text editor that is "too smart" when determining the
file content type (and thinks \"*it's a DOS text file*\") file content type (and thinks "*it's a DOS text file*")
- a direct copy and paste from certain webpages (some pastebins are - a direct copy and paste from certain webpages (some pastebins are
known for this) known for this)
@ -343,7 +343,7 @@ Here's what happens because of the `#!/bin/bash^M` in our shebang:
problem. problem.
- the script can't be executed - the script can't be executed
The error message can vary. If you\'re lucky, you\'ll get: The error message can vary. If you're lucky, you'll get:
bash: ./testing.sh: /bin/bash^M: bad interpreter: No such file or directory bash: ./testing.sh: /bin/bash^M: bad interpreter: No such file or directory
@ -355,9 +355,10 @@ Why? Because when printed literally, the `^M` makes the cursor go back
to the beginning of the line. The whole error message is *printed*, but to the beginning of the line. The whole error message is *printed*, but
you *see* only part of it! you *see* only part of it!
<note warning> It's easy to imagine the `^M` is bad in other places !!! warning "warning"
too. If you get weird and illogical messages from your script, rule out It's easy to imagine the `^M` is bad in other places
the possibility that`^M` is involved. Find and eliminate it! </note> too. If you get weird and illogical messages from your script, rule out
the possibility that`^M` is involved. Find and eliminate it!
### How can I find and eliminate them? ### How can I find and eliminate them?
@ -376,7 +377,8 @@ the possibility that`^M` is involved. Find and eliminate it! </note>
- [the set builtin command](../commands/builtin/set.md) (for `-v` and `-x`) - [the set builtin command](../commands/builtin/set.md) (for `-v` and `-x`)
FIXME !!! warning "FIXME"
tbd.
- DEBUG trap - DEBUG trap
- BASH Debugger <http://bashdb.sourceforge.net/> - BASH Debugger <http://bashdb.sourceforge.net/>

View File

@ -17,8 +17,8 @@ Here are some typical traps:
### Your perfect Bash script executes with syntax errors ### Your perfect Bash script executes with syntax errors
If you write Bash scripts with Bash specific syntax and features, run If you write Bash scripts with Bash specific syntax and features, run
them with [Bash]{.underline}, and run them with Bash in [native them with <u>Bash</u>, and run them with Bash in <u>native
mode]{.underline}. mode</u>.
**Wrong**: **Wrong**:
@ -36,7 +36,7 @@ See also:
- [Bash startup mode: SH mode](../scripting/bashbehaviour.md#sh_mode) - [Bash startup mode: SH mode](../scripting/bashbehaviour.md#sh_mode)
- [Bash run mode: POSIX mode](../scripting/bashbehaviour.md#posix_run_mode) - [Bash run mode: POSIX mode](../scripting/bashbehaviour.md#posix_run_mode)
### Your script named \"test\" doesn't execute ### Your script named "test" doesn't execute
Give it another name. The executable `test` already exists. Give it another name. The executable `test` already exists.

View File

@ -21,27 +21,16 @@ e.g. if there is a corresponding POSIX(r)-compatible syntax (see
Some syntax elements have a BASH-specific, and a portable[^1]) pendant. Some syntax elements have a BASH-specific, and a portable[^1]) pendant.
In these cases the portable syntax should be preferred. In these cases the portable syntax should be preferred.
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |construct|portable equivalent|Description|Portability|
construct portable equivalent Description Portability |---------|-------------------|-----------|-----------|
------------------------------------------ --------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------------------------------------------- |`source FILE`|`. FILE`|include a script file|Bourne shell (bash, ksh, POSIX(r), zsh, …)|
`source\ FILE` `. FILE` include a script file Bourne shell (bash, ksh, POSIX(r), zsh, \...) |`declare` keyword|`typeset` keyword|define local variables (or variables with special attributes)|ksh, zsh, …, **not POSIX!**|
|`command <<< WORD`|`command <<MARKER`\n`WORD`\n`MARKER`|a here-string, a special form of the here-document, avoid it in portable scripts!|POSIX(r)|
`declare`\\ keyword `typeset` keyword define local variables (or variables with special attributes) ksh, zsh, \..., **not POSIX!** |`export VAR=VALUE`|`VAR=VALUE`\n`export VAR`|Though POSIX(r) allows it, some shells don't want the assignment and the exporting in one command|POSIX(r), zsh, ksh, …|
|`(( MATH ))`|`: $(( MATH ))`|POSIX(r) does't define an arithmetic compund command, many shells don't know it. Using the pseudo-command `:` and the arithmetic expansion `$(( ))` is a kind of workaround here. **Attention:** Not all shell support assignment like `$(( a = 1 + 1 ))`! Also see below for a probably more portable solution.|all POSIX(r) compatible shells|
`command\ <<<\ WORD` `command <<MARKER WORD MARKER` a here-string, a special form of the here-document, avoid it in portable scripts! POSIX(r) |`[[ EXPRESSION ]]`|`[ EXPRESSION ]`\nor\n`test EXPRESSION`|The Bashish test keyword is reserved by POSIX(r), but not defined. Use the old fashioned way with the `test` command. See [[web/20230315170826/https://wiki.bash-hackers.org/commands/classictest]]|POSIX(r) and others|
|`COMMAND < <( …INPUTCOMMANDS… )`|`INPUTCOMMANDS > TEMPFILE`\n`COMMAND < TEMPFILE`|Process substitution (here used with redirection); use the old fashioned way (tempfiles)|POSIX(r) and others|
`export VAR=VALUE` `VAR=VALUE export VAR` Though POSIX(r) allows it, some shells don't want the assignment and the exporting in one command POSIX(r), zsh, ksh, \... |`((echo X);(echo Y))`|`( (echo X); (echo Y) )`|Nested subshells (separate the inner `()` from the outer `()` by spaces, to not confuse the shell regarding arithmetic control operators)|POSIX(r) and others|
`(( MATH ))` `: $(( MATH ))` POSIX(r) does't define an arithmetic compund command, many shells don't know it. Using the pseudo-command `:` and the arithmetic expansion `$(( ))` is a kind of workaround here. **Attention:** Not all shell support assignment like `$(( a = 1 + 1 ))`! Also see below for a probably more portable solution. all POSIX(r) compatible shells
`[[\ EXPRESSION\ ]]` `[ EXPRESSION ]`\ The Bashish test keyword is reserved by POSIX(r), but not defined. Use the old fashioned way with the `test` command. See [the classic test command](../commands/classictest.md) POSIX(r) and others
or\
`test EXPRESSION`
`COMMAND\ <\ <(\ ...INPUTCOMMANDS...\ )` `INPUTCOMMANDS\ >\ TEMPFILE COMMAND\ <\ TEMPFILE` Process substitution (here used with redirection); use the old fashioned way (tempfiles) POSIX(r) and others
`((echo X);(echo Y))` `( (echo X); (echo Y) )` Nested subshells (separate the inner `()` from the outer `()` by spaces, to not confuse the shell regarding arithmetic control operators) POSIX(r) and others
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Portability rationale ## Portability rationale
@ -51,8 +40,9 @@ will be!) and it's not very detailed (e.g. you won't find information
about how which shell technically forks off which subshell). It's just about how which shell technically forks off which subshell). It's just
an assorted small set of portability guidelines. *-Thebonsai* an assorted small set of portability guidelines. *-Thebonsai*
FIXME UNIX shell gurus out there, please be patient with a newbie like !!! warning "FIXME"
me and give comments and hints instead of flames. UNIX shell gurus out there, please be patient with a newbie like me
and give comments and hints instead of flames.
### Environment (exported) variables ### Environment (exported) variables
@ -100,7 +90,7 @@ Why? (list of known behaviours)
- may or may not automatically interpret backslash escpape codes in - may or may not automatically interpret backslash escpape codes in
the strings the strings
- may or may not automatically interpret switches (like `-n`) - may or may not automatically interpret switches (like `-n`)
- may or may not ignore \"end of options\" tag (`--`) - may or may not ignore "end of options" tag (`--`)
- `echo -n` and `echo -e` are neither portable nor standard (**even - `echo -n` and `echo -e` are neither portable nor standard (**even
within the same shell**, depending on the version or environment within the same shell**, depending on the version or environment
variables or the build options, especially KSH93 and Bash) variables or the build options, especially KSH93 and Bash)
@ -113,7 +103,7 @@ existance of [the `printf` command](../commands/builtin/printf.md).
- `${var:x:x}` is KSH93/Bash specific - `${var:x:x}` is KSH93/Bash specific
- `${var/../..}` and `${var//../..}` are KSH93/Bash specific - `${var/../..}` and `${var//../..}` are KSH93/Bash specific
- `var=$*` and `var=$@` are not handled the same in all shells if the - `var=$*` and `var=$@` are not handled the same in all shells if the
first char of IFS is not \" \" (space). `var="$*"` should work first char of IFS is not " " (space). `var="$*"` should work
(except the Bourne shell always joins the expansions with space) (except the Bourne shell always joins the expansions with space)
### Special variables ### Special variables
@ -130,11 +120,11 @@ of your script:
#### RANDOM #### RANDOM
[RANDOM](../syntax/shellvars.md#RANDOM) is Bash/KSH/ZSH specific variable [RANDOM](../syntax/shellvars.md#RANDOM) is Bash/KSH/ZSH specific variable
that will give you a random number up to 32767 (2\^15-1). Among many that will give you a random number up to 32767 (2^15-1). Among many
other available external options, you can use awk to generate a random other available external options, you can use awk to generate a random
number. There are multiple implementations of awk and which version your number. There are multiple implementations of awk and which version your
system uses will depend. Most modern systems will call \'gawk\' (i.e. system uses will depend. Most modern systems will call 'gawk' (i.e.
GNU awk) or \'nawk\'. \'oawk\' (i.e. Original/Old awk) does not have the GNU awk) or 'nawk'. 'oawk' (i.e. Original/Old awk) does not have the
rand() or srand() functions, so is best avoided. rand() or srand() functions, so is best avoided.
# 'gawk' can produce random numbers using srand(). In this example, 10 integers between 1 and 500: # 'gawk' can produce random numbers using srand(). In this example, 10 integers between 1 and 500:
@ -143,10 +133,10 @@ rand() or srand() functions, so is best avoided.
# 'nawk' and 'mawk' does the same, but needs a seed to be provided for its rand() function. In this example we use $(date) # 'nawk' and 'mawk' does the same, but needs a seed to be provided for its rand() function. In this example we use $(date)
randpm=$(mawk -v min=1 -v max=500 -v nNum=10 -v seed="$(date +%Y%M%d%H%M%S)" 'BEGIN { srand(seed); for (i = 0; i < nNum; ++i) {print int(min + rand() * (max - min)} }') randpm=$(mawk -v min=1 -v max=500 -v nNum=10 -v seed="$(date +%Y%M%d%H%M%S)" 'BEGIN { srand(seed); for (i = 0; i < nNum; ++i) {print int(min + rand() * (max - min)} }')
*Yes, I\'m not an `awk` expert, so please correct it, rather than *Yes, I'm not an `awk` expert, so please correct it, rather than
complaining about possible stupid code!* complaining about possible stupid code!*
# Well, seeing how this //is// BASH-hackers.org I kinda missed the bash way of doing the above ;-) # Well, seeing how this //is// BASH-hackers.org I kinda missed the bash way of doing the above ;-)
# print a number between 0 and 500 :-) # print a number between 0 and 500 :-)
printf $(( 500 * RANDOM / 32767 )) printf $(( 500 * RANDOM / 32767 ))
@ -162,7 +152,7 @@ Find another method.
The [PATH](../syntax/shellvars.md#PATH) variable is a colon-delimited list of The [PATH](../syntax/shellvars.md#PATH) variable is a colon-delimited list of
directory names, so it's basically possible to run a loop and check directory names, so it's basically possible to run a loop and check
every `PATH` component for the command you\'re looking for and for every `PATH` component for the command you're looking for and for
executability. executability.
However, this method doesn't look nice. There are other ways of doing However, this method doesn't look nice. There are other ways of doing
@ -207,6 +197,6 @@ accessible by `PATH`:
echo "sed is available" echo "sed is available"
fi fi
[^1]: \"portable\" doesn't necessarily mean it's POSIX, it can also [^1]: "portable" doesn't necessarily mean it's POSIX, it can also
mean it's \"widely used and accepted\", and thus maybe more mean it's "widely used and accepted", and thus maybe more
portable than POSIX(r portable than POSIX(r

View File

@ -15,6 +15,8 @@ obsolete by some measure. A thorough discussion of the rationale is
beyond the scope of this page. See the [portability beyond the scope of this page. See the [portability
page](../scripting/nonportable.md) for a discussion on portability issues. page](../scripting/nonportable.md) for a discussion on portability issues.
## Tolerated but few ligitimate uses
This first table lists syntax that is tolerated by Bash but has few if This first table lists syntax that is tolerated by Bash but has few if
any legitimate uses. These features exist mostly for Bourne, csh, or any legitimate uses. These features exist mostly for Bourne, csh, or
some other backward compatibility with obsolete shells, or were some other backward compatibility with obsolete shells, or were
@ -24,13 +26,16 @@ everyone except maybe code golfers. New scripts should never use them.
None of the items on this list are specified by the most current version None of the items on this list are specified by the most current version
of POSIX, and some may be incompatible with POSIX. of POSIX, and some may be incompatible with POSIX.
Syntax Replacement Description |Syntax|Replacement|Description|
---------------------------------- --------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |--|--|--|
`&>FILE` and `>&FILE` `>FILE 2>&1` This redirection syntax is short for `>FILE 2>&1` and originates in the C Shell. The latter form is especially uncommon and should never be used, and the explicit form using separate redirections is preferred over both. These shortcuts contribute to confusion about the copy descriptor because the syntax is unclear. They also introduce parsing ambiguity, and conflict with POSIX. Shells without this feature treat `cmd1 &>file cmd2` as: \"background `cmd1` and then execute `cmd2` with its stdout redirected to `file`\", which is the correct interpretation of this expression. See: [redirection](../syntax/redirection.md) \`\$ { bash; dash </dev/fd/0; } <<<\'echo foo>/dev/null&>/dev/fd/2 echo bar\' foo echo bar bar\` |`&>FILE` and `>&FILE`|`>FILE 2>&1`|This redirection syntax is short for `>FILE 2>&1` and originates in the C Shell. The latter form is especially uncommon and should never be used, and the explicit form using separate redirections is preferred over both. These shortcuts contribute to confusion about the copy descriptor because the syntax is unclear. They also introduce parsing ambiguity, and conflict with POSIX. Shells without this feature treat `cmd1 &>file cmd2` as: "background `cmd1` and then execute `cmd2` with its stdout redirected to `file`", which is the correct interpretation of this expression. See: [redirection](../syntax/redirection.md) <pre>$ { bash; dash </dev/fd/0; } <<<'echo foo>/dev/null&>/dev/fd/2 echo bar'<br>foo echo bar<br>bar</pre>|
`$[EXPRESSION]` `$((EXPRESSION))` This undocumented syntax is completely replaced by the POSIX-conforming arithmetic expansion `$((EXPRESSION))`. It is unimplemented almost everywhere except Bash and Zsh. See [arithmetic expansion](../syntax/expansion/arith.md). [Some discussion](http://lists.gnu.org/archive/html/bug-bash/2012-04/msg00034.html). |`$[EXPRESSION]`|`$((EXPRESSION))`|This undocumented syntax is completely replaced by the POSIX-conforming arithmetic expansion `$((EXPRESSION))`. It is unimplemented almost everywhere except Bash and Zsh. See [arithmetic expansion](../syntax/expansion/arith.md). [Some discussion](http://lists.gnu.org/archive/html/bug-bash/2012-04/msg00034.html).|
`COMMAND\ |&\ COMMAND` `COMMAND 2>&1 | COMMAND` This is an alternate pipeline operator derived from Zsh. Officially, it is not considered deprecated by Bash, but I highly discourage it. It conflicts with the list operator used for [coprocess](../syntax/keywords/coproc.md) creation in most Korn shells. It also has confusing behavior. The stdout is redirected first like an ordinary pipe, while the stderr is actually redirected last -- after other redirects preceding the pipe operator. Overall, it's pointless syntax bloat. Use an explicit redirect instead. |`COMMAND|& COMMAND`|`COMMAND 2>&1| COMMAND`|This is an alternate pipeline operator derived from Zsh. Officially, it is not considered deprecated by Bash, but I highly discourage it. It conflicts with the list operator used for [coprocess](../syntax/keywords/coproc.md) creation in most Korn shells. It also has confusing behavior. The stdout is redirected first like an ordinary pipe, while the stderr is actually redirected last after other redirects preceding the pipe operator. Overall, it's pointless syntax bloat. Use an explicit redirect instead.|
`function\ NAME()\ COMPOUND-CMD` `NAME()\ COMPOUND-CMD` or `function\ NAME\ {\ CMDS;\ }` This is an amalgamation between the Korn and POSIX style function definitions - using both the `function` keyword and parentheses. It has no useful purpose and no historical basis or reason to exist. It is not specified by POSIX. It is accepted by Bash, mksh, zsh, and perhaps some other Korn shells, where it is treated as identical to the POSIX-style function. It is not accepted by AT&T ksh. It should never be used. See the next table for the `function` keyword. Bash doesn't have this feature documented as expressly deprecated. |`function NAME() COMPOUND-CMD`|`NAME() COMPOUND-CMD` or `function NAME { CMDS; }`|This is an amalgamation between the Korn and POSIX style function definitions - using both the `function` keyword and parentheses. It has no useful purpose and no historical basis or reason to exist. It is not specified by POSIX. It is accepted by Bash, mksh, zsh, and perhaps some other Korn shells, where it is treated as identical to the POSIX-style function. It is not accepted by AT&T ksh. It should never be used. See the next table for the `function` keyword. Bash doesn't have this feature documented as expressly deprecated.|
`for x; { ...;}` `do`, `done`, `in`, `esac`, etc. This undocumented syntax replaces the `do` and `done` reserved words with braces. Many Korn shells support various permutations on this syntax for certain compound commands like `for`, `case`, and `while`. Which ones and certain details like whether a newline or semicolon are required vary. Only `for` works in Bash. Needless to say, don't use it. |`for x; { ...;}`|`do`, `done`, `in`, `esac`, etc.|This undocumented syntax replaces the `do` and `done` reserved words with braces. Many Korn shells support various permutations on this syntax for certain compound commands like `for`, `case`, and `while`. Which ones and certain details like whether a newline or semicolon are required vary. Only `for` works in Bash. Needless to say, don't use it.|
## Syntax superseded by superior alternatives
This table lists syntax that is specified by POSIX (unless otherwise This table lists syntax that is specified by POSIX (unless otherwise
specified below), but has been superseded by superior alternatives specified below), but has been superseded by superior alternatives
@ -39,43 +44,33 @@ reasons such as encouraging bad practices or dangerous code. Those that
are specified by POSIX may be badly designed and unchangeable for are specified by POSIX may be badly designed and unchangeable for
historical reasons. historical reasons.
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |Syntax|Replacement|Description|
Syntax Replacement Description |------|-----------|-----------|
----------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |Unquoted expansions, [wordsplitting](../syntax/expansion/wordsplit.md), and [Pathname expansion (globbing)](../syntax/expansion/globs.md)|[Proper quoting](http://mywiki.wooledge.org/Quotes), Ksh/Bash-style [arrays](../syntax/arrays.md), The "$@" expansion, [the read builtin command](../commands/builtin/read.md)|*Quoting errors* are a broad category of common mistakes brought about by a few unintuitive features carried over from the Bourne shell due to complaints of broken scripts and changes in previously documented behavior. Most of the important expansions are performed at the same time from left to right. However, a few expansions, most notably word-splitting and globbing, and in shells other than Bash, [brace expansion](../syntax/expansion/brace.md), are performed **on the results of previous expansions, by default, unless they are quoted.** This means that the act of expanding an unquoted variable in an ordinary argument context, depending on the value of the variable, can yield different results depending on possibly uncontrolled side-effects like the value of `IFS`, and the names of files in the current working directory. You can't get globbing without word-splitting, or vice versa (without `set -f`). [You can't store a command or character-delimited list in a variable and safely evaluate it with unquoted expansion](http://mywiki.wooledge.org/BashFAQ/050). If possible, always choose a shell that supports Korn shell arrays such as Bash. They are a vital but non-standard feature for writing clean, safe scripts. Well-written scripts don't use word-splitting. A few exceptions are listed on the [word splitting page](../syntax/expansion/wordsplit.md). A significant proportion of the issues on the famous [Pitfalls list](http://mywiki.wooledge.org/BashPitfalls) fall under this category. See also: *[Don't read lines with for!](http://mywiki.wooledge.org/DontReadLinesWithFor)*|
Unquoted expansions, [wordsplit](../syntax/expansion/wordsplit.md), and [globs](../syntax/expansion/globs.md) [Proper quoting](http://mywiki.wooledge.org/Quotes), Ksh/Bash-style [arrays](../syntax/arrays.md), The \"\$@\" expansion, [read](../commands/builtin/read.md) *Quoting errors* are a broad category of common mistakes brought about by a few unintuitive features carried over from the Bourne shell due to complaints of broken scripts and changes in previously documented behavior. Most of the important expansions are performed at the same time from left to right. However, a few expansions, most notably word-splitting and globbing, and in shells other than Bash, [brace expansion](../syntax/expansion/brace.md), are performed **on the results of previous expansions, by default, unless they are quoted.** This means that the act of expanding an unquoted variable in an ordinary argument context, depending on the value of the variable, can yield different results depending on possibly uncontrolled side-effects like the value of `IFS`, and the names of files in the current working directory. You can't get globbing without word-splitting, or vice versa (without `set -f`). [You can't store a command or character-delimited list in a variable and safely evaluate it with unquoted expansion](http://mywiki.wooledge.org/BashFAQ/050). If possible, always choose a shell that supports Korn shell arrays such as Bash. They are a vital but non-standard feature for writing clean, safe scripts. Well-written scripts don't use word-splitting. A few exceptions are listed on the [word splitting page](../syntax/expansion/wordsplit.md). A significant proportion of the issues on the famous [Pitfalls list](http://mywiki.wooledge.org/BashPitfalls) fall under this category. See also: *[Don't read lines with for!](http://mywiki.wooledge.org/DontReadLinesWithFor)* |``COMMANDS``|`$(COMMANDS)`|his is the older Bourne-compatible form of the [command substitution](../syntax/expansion/cmdsubst.md). Both the `` `COMMANDS` `` and `$(COMMANDS)` syntaxes are specified by POSIX, but the latter is [greatly]{.underline} preferred, though the former is unfortunately still very prevalent in scripts. New-style command substitutions are widely implemented by every modern shell (and then some). The only reason for using backticks is for compatibility with a real Bourne shell (like Heirloom). Backtick command substitutions require special escaping when nested, and examples found in the wild are improperly quoted more often than not. See: *[Why is $(...) preferred over `...` (backticks)?](http://mywiki.wooledge.org/BashFAQ/082)*.|
|`[ EXPRESSION ]` and `test EXPRESSION`|`[[ EXPRESSION ]]`|`test` and `[` are the Bourne/POSIX commands for evaluating test expressions (they are almost identical, and `[` is somewhat more common). The expressions consist of regular arguments, unlike the Ksh/Bash `[[` command. While the issue is analogous to `let` vs `((`, the advantages of `[[` vs `[` are even more important because the arguments/expansions aren't just concatenated into one expression. With the classic `[` command, the number of arguments is significant. If at all possible, use the [conditional expression](../syntax/ccmd/conditional_expression.md) ("new test command") `[[ EXPRESSION ]]`. Unless there is a need for POSIX compatibility, there are only a few reasons to use `[`. `[[` is one of the most portable and consistent non-POSIX ksh extensions available. See: [conditional_expression](../syntax/ccmd/conditional_expression.md) and *[What is the difference between test, \[ and \[\[ ?](http://mywiki.wooledge.org/BashFAQ/031)*|
|`set -e`, `set -o errexit` and the `ERR` trap|proper control flow and error handling|`set -e` causes untested non-zero exit statuses to be fatal. It is a debugging feature intended for use only during development and should not be used in production code, especially init scripts and other high-availability scripts. Do not be tempted to think of this as "error handling"; it's not, it's just a way to find the place you've *forgotten* to put error handling.<br>Think of it as akin to `use strict` in Perl or `throws` in C++: tough love that makes you write better code. Many guides recommend avoiding it entirely because of the apparently-complex rules for when non-zero statuses cause the script to abort. Conversely, large software projects with experienced coders may recommend or even mandate its use.<br>Because it provides no notification of the location of the error, it's more useful combined with `set -x` or the `DEBUG` trap and other Bash debug features, and both flags are normally better set on the command line rather than within the script itself.<br>Most of this also applies to the `ERR` trap, though I've seen it used in a few places in shells that lack `pipefail` or `PIPESTATUS`. The `ERR` trap is not POSIX, but `set -e` is. `failglob` is another Bash feature that falls into this category (mainly useful for debugging).<br>**The `set -e` feature generates more questions and false bug reports on the Bash mailing list than all other features combined!** Please do not rely on `set -e` for logic in scripts. If you still refuse to take this advice, make sure you understand **exactly** how it works. See: *[Why doesn't set -e (or set -o errexit, or trap ERR) do what I expected?](http://mywiki.wooledge.org/BashFAQ/105)* and <http://www.fvue.nl/wiki/Bash:_Error_handling>|
|`set -u` or `set -o nounset`|Proper control flow and error handling|`set -u` causes attempts to expand unset variables or parameters as fatal errors. Like `set -e`, it bypasses control flow and exits immediately from the current shell environment. Like non-zero statuses, unset variables are a normal part of most non-trivial shell scripts. Living with `set -u` requires hacks like `${1+"$1"}` for each expansion that might possibly be unset. Only very current shells guarantee that expanding `@` or `*` won't trigger an error when no parameters are set (<http://austingroupbugs.net/view.php?id=155>, <http://www.in-ulm.de/~mascheck/various/bourne_args/>). Apparently some find it useful for debugging. See [How do I determine whether a variable is already defined? Or a function?](http://mywiki.wooledge.org/BashFAQ/083) for how to properly test for defined variables. Don't use `set -u`.|
|`${var?msg}` or `${var:?msg}`|Proper control flow and error handling|Like `set -u`, this expansion causes a fatal error which immediately exits the current shell environment if the given parameter is unset or is null. It prints the error message given, to the right of the operator. If a value is expected and you'd like to create an assertion or cause errors, it's better to test for undefined variables using one of [these techniques](http://mywiki.wooledge.org/BashFAQ/083) and handle the error manually, or call a `die` function. This expansion is defined by POSIX. It's better than `set -u`, because it's explicit, but not by much. It also allows you to accidentally construct hilariously deceptive error messages: <pre>bash -c 'f() { definitely_not_printf "${printf:?"$1" - No such option}"; }; f -v'<br>bash: printf: -v - No such option</pre>|
`` `COMMANDS` `` `$(COMMANDS)` This is the older Bourne-compatible form of the [command substitution](../syntax/expansion/cmdsubst.md). Both the `` `COMMANDS` `` and `$(COMMANDS)` syntaxes are specified by POSIX, but the latter is [greatly]{.underline} preferred, though the former is unfortunately still very prevalent in scripts. New-style command substitutions are widely implemented by every modern shell (and then some). The only reason for using backticks is for compatibility with a real Bourne shell (like Heirloom). Backtick command substitutions require special escaping when nested, and examples found in the wild are improperly quoted more often than not. See: *[Why is \$(\...) preferred over \`\...\` (backticks)?](http://mywiki.wooledge.org/BashFAQ/082)*. # Frequently misued
`[\ EXPRESSION\ ]`\\ and\\ `test\ EXPRESSION` `[[\ EXPRESSION\ ]]` `test` and `[` are the Bourne/POSIX commands for evaluating test expressions (they are almost identical, and `[` is somewhat more common). The expressions consist of regular arguments, unlike the Ksh/Bash `[[` command. While the issue is analogous to `let` vs `((`, the advantages of `[[` vs `[` are even more important because the arguments/expansions aren't just concatenated into one expression. With the classic `[` command, the number of arguments is significant. If at all possible, use the [conditional expression](../syntax/ccmd/conditional_expression.md) (\"new test command\") `[[ EXPRESSION ]]`. Unless there is a need for POSIX compatibility, there are only a few reasons to use `[`. `[[` is one of the most portable and consistent non-POSIX ksh extensions available. See: [conditional_expression](../syntax/ccmd/conditional_expression.md) and *[What is the difference between test, \[ and \[\[ ?](http://mywiki.wooledge.org/BashFAQ/031)*
`set -e`, `set -o errexit`\ proper control flow and error handling `set -e` causes untested non-zero exit statuses to be fatal. It is a debugging feature intended for use only during development and should not be used in production code, especially init scripts and other high-availability scripts. Do not be tempted to think of this as \"error handling\"; it's not, it's just a way to find the place you\'ve *forgotten* to put error handling.\
and the `ERR` trap Think of it as akin to `use strict` in Perl or `throws` in C++: tough love that makes you write better code. Many guides recommend avoiding it entirely because of the apparently-complex rules for when non-zero statuses cause the script to abort. Conversely, large software projects with experienced coders may recommend or even mandate its use.\
Because it provides no notification of the location of the error, it's more useful combined with `set -x` or the `DEBUG` trap and other Bash debug features, and both flags are normally better set on the command line rather than within the script itself.\
Most of this also applies to the `ERR` trap, though I\'ve seen it used in a few places in shells that lack `pipefail` or `PIPESTATUS`. The `ERR` trap is not POSIX, but `set -e` is. `failglob` is another Bash feature that falls into this category (mainly useful for debugging).\
**The `set -e` feature generates more questions and false bug reports on the Bash mailing list than all other features combined!** Please do not rely on `set -e` for logic in scripts. If you still refuse to take this advice, make sure you understand **exactly** how it works. See: *[Why doesn't set -e (or set -o errexit, or trap ERR) do what I expected?](http://mywiki.wooledge.org/BashFAQ/105)* and <http://www.fvue.nl/wiki/Bash:_Error_handling>
`set -u` or `set -o nounset` Proper control flow and error handling `set -u` causes attempts to expand unset variables or parameters as fatal errors. Like `set -e`, it bypasses control flow and exits immediately from the current shell environment. Like non-zero statuses, unset variables are a normal part of most non-trivial shell scripts. Living with `set -u` requires hacks like `${1+"$1"}` for each expansion that might possibly be unset. Only very current shells guarantee that expanding `@` or `*` won't trigger an error when no parameters are set (<http://austingroupbugs.net/view.php?id=155>, <http://www.in-ulm.de/~mascheck/various/bourne_args/>). Apparently some find it useful for debugging. See *[How do I determine whether a variable is already defined? Or a function?](http://mywiki.wooledge.org/BashFAQ/083)* for how to properly test for defined variables. Don't use `set -u`.
`${var?msg}` or `${var:?msg}` Proper control flow and error handling Like `set -u`, this expansion causes a fatal error which immediately exits the current shell environment if the given parameter is unset or is null. It prints the error message given, to the right of the operator. If a value is expected and you\'d like to create an assertion or cause errors, it's better to test for undefined variables using one of [these techniques](http://mywiki.wooledge.org/BashFAQ/083) and handle the error manually, or call a `die` function. This expansion is defined by POSIX. It's better than `set -u`, because it's explicit, but not by much. It also allows you to accidentally construct hilariously deceptive error messages: `bash -c 'f() { definitely_not_printf "${printf:?"$1" - No such option}"; }; f -v'
bash: printf: -v - No such option`
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
This table lists features that are used only if you have a specific This table lists features that are used only if you have a specific
reason to prefer it over another alternative. These have some legitimate reason to prefer it over another alternative. These have some legitimate
uses if you know what you\'re doing, such as for those with specific uses if you know what you're doing, such as for those with specific
portability requirements, or in order to make use of some subtle portability requirements, or in order to make use of some subtle
behavioral differences. These are frequently (mis)used for no reason. behavioral differences. These are frequently (mis)used for no reason.
Writing portable scripts that go outside of POSIX features requires Writing portable scripts that go outside of POSIX features requires
knowing how to account for many (often undocumented) differences across knowing how to account for many (often undocumented) differences across
many shells. If you do happen to know what you\'re doing, don't be too many shells. If you do happen to know what you're doing, don't be too
surprised if you run across someone telling you not to use these. surprised if you run across someone telling you not to use these.
Syntax Replacement Description |Syntax|Replacement|Description|
------------------------------- --------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |--|--|--|
`function\ NAME\ {\ CMDS;\ }` `NAME()\ COMPOUND-CMD` This is the ksh form of function definition created to extend the Bourne and POSIX form with modified behaviors and additional features like local variables. The idea was for new-style functions to be analogous to regular builtins with their own environment and scope, while POSIX-style functions are more like special builtins. `function` is supported by almost every ksh-derived shell including Bash and Zsh, but isn't specified by POSIX. Bash treats all function styles the same, but this is unusual. `function` has some preferable characteristics in many ksh variants, making it more portable for scripts that use non-POSIX extensions by some measures. If you\'re going to use the `function` keyword, it implies that you\'re either targeting Ksh specifically, or that you have detailed knowledge of how to compensate for differences across shells. It should always be used consistently with `typeset`, but never used with `declare` or `local`. Also in ksh93, the braces are not a [command group](../syntax/ccmd/grouping_plain.md), but a required part of the syntax (unlike Bash and others). See [shell function definitions](../syntax/basicgrammar.md#shell_function_definitions) |`function NAME { CMDS; }`|`NAME() COMPOUND-CMD`|This is the ksh form of function definition created to extend the Bourne and POSIX form with modified behaviors and additional features like local variables. The idea was for new-style functions to be analogous to regular builtins with their own environment and scope, while POSIX-style functions are more like special builtins. `function` is supported by almost every ksh-derived shell including Bash and Zsh, but isn't specified by POSIX. Bash treats all function styles the same, but this is unusual. `function` has some preferable characteristics in many ksh variants, making it more portable for scripts that use non-POSIX extensions by some measures. If you're going to use the `function` keyword, it implies that you're either targeting Ksh specifically, or that you have detailed knowledge of how to compensate for differences across shells. It should always be used consistently with `typeset`, but never used with `declare` or `local`. Also in ksh93, the braces are not a [command group](../syntax/ccmd/grouping_plain), but a required part of the syntax (unlike Bash and others). See [shell function definitions](../syntax/basicgrammar#shell_function_definitions)|
`typeset` `declare`, `local`, `export`, `readonly` This is closely related to the above, and should often be used together. `typeset` exists primarily for `ksh` compatibility, but is marked as \"deprecated\" in Bash (though I don't entirely agree with this). This makes some sense, because future compatibility can't be guaranteed, and any compatibility at all, requires understanding the non-POSIX features of other shells and their differences. Using `declare` instead of `typeset` emphasizes your intention to be \"Bash-only\", and definitely breaks everywhere else (except possibly zsh if you\'re lucky). The issue is further complicated by Dash and the [Debian policy](http://www.debian.org/doc/debian-policy/ch-files.html#s-scripts) requirement for a `local` builtin, which is itself not entirely compatible with Bash and other shells. |`typeset`|`declare`, `local`, `export`, `readonly`|This is closely related to the above, and should often be used together. `typeset` exists primarily for `ksh` compatibility, but is marked as "deprecated" in Bash (though I don't entirely agree with this). This makes some sense, because future compatibility can't be guaranteed, and any compatibility at all, requires understanding the non-POSIX features of other shells and their differences. Using `declare` instead of `typeset` emphasizes your intention to be "Bash-only", and definitely breaks everywhere else (except possibly zsh if you're lucky). The issue is further complicated by Dash and the [Debian policy](http://www.debian.org/doc/debian-policy/ch-files.html#s-scripts) requirement for a `local` builtin, which is itself not entirely compatible with Bash and other shells.|
\'\'let \'EXPR\' \'\' `((EXPR))` or `[\ $((EXPR))\ -ne\ 0 ]` `let` is the \"simple command\" variant of arithmetic evaluation command, which takes regular arguments. Both `let` and `((expr))` were present in ksh88, and everything that supports one should support the other. Neither are POSIX. The compound variant is preferable because it doesn't take regular arguments for [wordsplitting](../syntax/expansion/wordsplit.md) and [globbing](../syntax/expansion/globs.md), which makes it safer and clearer. It is also usually faster, especially in Bash, where compound commands are typically significantly faster. Some of the (few) reasons for using `let` are detailed on the [let](../commands/builtin/let.md) page. See [arithmetic evaluation compound command](../syntax/ccmd/arithmetic_eval.md) |`let 'EXPR' `|`((EXPR))` or `[ $((EXPR)) -ne 0 ]`|`let` is the "simple command" variant of arithmetic evaluation command, which takes regular arguments. Both `let` and `((expr))` were present in ksh88, and everything that supports one should support the other. Neither are POSIX. The compound variant is preferable because it doesn't take regular arguments for [wordsplitting](../syntax/expansion/wordsplit) and [globbing](../syntax/expansion/globs), which makes it safer and clearer. It is also usually faster, especially in Bash, where compound commands are typically significantly faster. Some of the (few) reasons for using `let` are detailed on the [let](../commands/builtin/let) page. See [arithmetic evaluation compound command](../syntax/ccmd/arithmetic_eval)|
`eval` Depends. Often code can be restructured to use better alternatives. `eval` is thrown in here for good measure, as sadly it is so often misused that any use of `eval` (even the rare clever one) is immediately dismissed as wrong by experts, and among the most immediate solutions abused by beginners. In reality, there are correct ways to use `eval`, and even cases in which it's necessary, even in sophisticated shells like Bash and Ksh. `eval` is unusual in that it is less frequently appropriate in more feature-rich shells than in more minimal shells like Dash, where it is used to compensate for more limitations. If you find yourself needing `eval` too frequently, it might be a sign that you\'re either better off using a different language entirely, or trying to borrow an idiom from some other paradigm that isn't well suited to the shell language. By the same token, there are some cases in which working too hard to avoid `eval` ends up adding a lot of complexity and sacrificing all portability. Don't substitute a clever `eval` for something that's a bit \"too clever\", just to avoid the `eval`, yet, take reasonable measures to avoid it where it is sensible to do so. See: [eval](../commands/builtin/eval.md) and [Eval command and security issues](http://mywiki.wooledge.org/BashFAQ/048). |`eval`|Depends. Often code can be restructured to use better alternatives.|`eval` is thrown in here for good measure, as sadly it is so often misused that any use of `eval` (even the rare clever one) is immediately dismissed as wrong by experts, and among the most immediate solutions abused by beginners. In reality, there are correct ways to use `eval`, and even cases in which it's necessary, even in sophisticated shells like Bash and Ksh. `eval` is unusual in that it is less frequently appropriate in more feature-rich shells than in more minimal shells like Dash, where it is used to compensate for more limitations. If you find yourself needing `eval` too frequently, it might be a sign that you're either better off using a different language entirely, or trying to borrow an idiom from some other paradigm that isn't well suited to the shell language. By the same token, there are some cases in which working too hard to avoid `eval` ends up adding a lot of complexity and sacrificing all portability. Don't substitute a clever `eval` for something that's a bit "too clever", just to avoid the `eval`, yet, take reasonable measures to avoid it where it is sensible to do so. See: [The eval builtin command](../commands/builtin/eval) and [Eval command and security issues](http://mywiki.wooledge.org/BashFAQ/048 "http://mywiki.wooledge.org/BashFAQ/048").|
## See also ## See also

View File

@ -17,15 +17,15 @@ The day will come when you want to give arguments to your scripts. These
arguments are known as **positional parameters**. Some relevant special arguments are known as **positional parameters**. Some relevant special
parameters are described below: parameters are described below:
Parameter(s) Description |Parameter(s)|Description|
------------------ ------------------------------------------------------------------------------------------------------------------------------------ |------------|-----------|
`$0` the first positional parameter, equivalent to `argv[0]` in C, see [the first argument](../scripting/posparams.md#the_first_argument) |`$0`|the first positional parameter, equivalent to `argv[0]` in C, see [the first argument](../scripting/posparams.md#the_first_argument)|
`$FUNCNAME` the function name ([**attention**]{.underline}: inside a function, `$0` is still the `$0` of the shell, **not** the function name) |`$FUNCNAME`|the function name (<u>**attention**</u>: inside a function, `$0` is still the `$0` of the shell, **not** the function name)|
`$1 ... $9` the argument list elements from 1 to 9 |`$1 ... $9`|the argument list elements from 1 to 9|
`${10} ... ${N}` the argument list elements beyond 9 (note the [parameter expansion](../syntax/pe.md) syntax!) |`${10} ... ${N}`|the argument list elements beyond 9 (note the [parameter expansion](../syntax/pe.md) syntax!)|
`$*` all positional parameters except `$0`, see [mass usage](../scripting/posparams.md#mass_usage) |`$*`|all positional parameters except `$0`, see [mass usage](../scripting/posparams.md#mass_usage)|
`$@` all positional parameters except `$0`, see [mass usage](../scripting/posparams.md#mass_usage) |`$@`|all positional parameters except `$0`, see [mass usage](../scripting/posparams.md#mass_usage)|
`$#` the number of arguments, not counting `$0` |`$#`|the number of arguments, not counting `$0`|
These positional parameters reflect exactly what was given to the script These positional parameters reflect exactly what was given to the script
when it was called. when it was called.
@ -33,8 +33,7 @@ when it was called.
Option-switch parsing (e.g. `-h` for displaying help) is not performed Option-switch parsing (e.g. `-h` for displaying help) is not performed
at this point. at this point.
See also [the dictionary entry for See also [the dictionary entry for "parameter"](../dict/parameter.md).
\"parameter\"](../dict/parameter.md).
## The first argument ## The first argument
@ -42,15 +41,15 @@ The very first argument you can access is referenced as `$0`. It is
usually set to the script's name exactly as called, and it's set on usually set to the script's name exactly as called, and it's set on
shell initialization: shell initialization:
[Testscript]{.underline} - it just echos `$0`: <u>Testscript</u> - it just echos `$0`:
#!/bin/bash #!/bin/bash
echo "$0" echo "$0"
You see, `$0` is always set to the name the script is called with (`>` You see, `$0` is always set to the name the script is called with (`>`
is the prompt\...): is the prompt...):
> ./testscript > ./testscript
./testscript ./testscript
> /usr/bin/testscript > /usr/bin/testscript
@ -79,7 +78,7 @@ values:
- `$1` will be discarded - `$1` will be discarded
- `$2` will become `$1` - `$2` will become `$1`
- `$3` will become `$2` - `$3` will become `$2`
- \... - ...
- in general: `$N` will become `$N-1` - in general: `$N` will become `$N-1`
The command can take a number as argument: Number of positions to shift. The command can take a number as argument: Number of positions to shift.
@ -139,7 +138,7 @@ a given wordlist. The loop uses the positional parameters as a wordlist:
echo "$arg" echo "$arg"
done done
[Advantage:]{.underline} The positional parameters will be preserved <u>Advantage:</u> The positional parameters will be preserved
------------------------------------------------------------------------ ------------------------------------------------------------------------
@ -172,7 +171,7 @@ There is a [small tutorial dedicated to
### All Positional Parameters ### All Positional Parameters
Sometimes it's necessary to just \"relay\" or \"pass\" given arguments Sometimes it's necessary to just "relay" or "pass" given arguments
to another program. It's very inefficient to do that in one of these to another program. It's very inefficient to do that in one of these
loops, as you will destroy integrity, most likely (spaces!). loops, as you will destroy integrity, most likely (spaces!).
@ -180,27 +179,27 @@ The shell developers created `$*` and `$@` for this purpose.
As overview: As overview:
Syntax Effective result |Syntax|Effective result|
-------- ----------------------------- |-------|----------------------------|
`$*` `$1 $2 $3 ... ${N}` |`$*`|`$1 $2 $3 ... ${N}`|
`$@` `$1 $2 $3 ... ${N}` |`$@`|`$1 $2 $3 ... ${N}`|
`"$*"` `"$1c$2c$3c...c${N}"` |`"$*"`|`"$1c$2c$3c...c${N}"`|
`"$@"` `"$1" "$2" "$3" ... "${N}"` |`"$@"`|`"$1" "$2" "$3" ... "${N}"`|
Without being quoted (double quotes), both have the same effect: All Without being quoted (double quotes), both have the same effect: All
positional parameters from `$1` to the last one used are expanded positional parameters from `$1` to the last one used are expanded
without any special handling. without any special handling.
When the `$*` special parameter is double quoted, it expands to the When the `$*` special parameter is double quoted, it expands to the
equivalent of: `"$1c$2c$3c$4c........$N"`, where \'c\' is the first equivalent of: `"$1c$2c$3c$4c........$N"`, where 'c' is the first
character of `IFS`. character of `IFS`.
But when the `$@` special parameter is used inside double quotes, it But when the `$@` special parameter is used inside double quotes, it
expands to the equivanent of\... expands to the equivanent of...
`"$1" "$2" "$3" "$4" ..... "$N"` `"$1" "$2" "$3" "$4" ..... "$N"`
\...which **reflects all positional parameters as they were set ...which **reflects all positional parameters as they were set
initially** and passed to the script or function. If you want to re-use initially** and passed to the script or function. If you want to re-use
your positional parameters to **call another program** (for example in a your positional parameters to **call another program** (for example in a
wrapper-script), then this is the choice for you, use double quoted wrapper-script), then this is the choice for you, use double quoted
@ -234,12 +233,12 @@ reverse starting with the last one.
`COUNT` may not be negative, i.e. the element count may not be `COUNT` may not be negative, i.e. the element count may not be
decremented. decremented.
[**Example:**]{.underline} START at the last positional parameter: <u>**Example:**</u> START at the last positional parameter:
echo "${@: -1}" echo "${@: -1}"
[**Attention**]{.underline}: As of Bash 4, a `START` of `0` includes the <u>**Attention**</u>: As of Bash 4, a `START` of `0` includes the
special parameter `$0`, i.e. the shell name or whatever \$0 is set to, special parameter `$0`, i.e. the shell name or whatever `$0` is set to,
when the positional parameters are in use. A `START` of `1` begins at when the positional parameters are in use. A `START` of `1` begins at
`$1`. In Bash 3 and older, both `0` and `1` began at `$1`. `$1`. In Bash 3 and older, both `0` and `1` began at `$1`.
@ -247,7 +246,7 @@ when the positional parameters are in use. A `START` of `1` begins at
Setting positional parameters with command line arguments, is not the Setting positional parameters with command line arguments, is not the
only way to set them. The [builtin command, set](../commands/builtin/set.md) only way to set them. The [builtin command, set](../commands/builtin/set.md)
may be used to \"artificially\" change the positional parameters from may be used to "artificially" change the positional parameters from
inside the script or function: inside the script or function:
set "This is" my new "set of" positional parameters set "This is" my new "set of" positional parameters
@ -260,7 +259,7 @@ inside the script or function:
# $5: positional # $5: positional
# $6: parameters # $6: parameters
It's wise to signal \"end of options\" when setting positional It's wise to signal "end of options" when setting positional
parameters this way. If not, the dashes might be interpreted as an parameters this way. If not, the dashes might be interpreted as an
option switch by `set` itself: option switch by `set` itself:
@ -273,7 +272,8 @@ flags, which may otherwise be reset by `set`
set -$- ... set -$- ...
FIXME continue !!! warning "FIXME"
continue
## Production examples ## Production examples
@ -281,7 +281,7 @@ FIXME continue
To make your program accept options as standard command syntax: To make your program accept options as standard command syntax:
`COMMAND [options] <params>` \# Like \'cat -A file.txt\' `COMMAND [options] <params> # Like 'cat -A file.txt'`
See simple option parsing code below. It's not that flexible. It See simple option parsing code below. It's not that flexible. It
doesn't auto-interpret combined options (-fu USER) but it works and is doesn't auto-interpret combined options (-fu USER) but it works and is
@ -343,8 +343,8 @@ a good rudimentary way to parse your arguments.
This simple wrapper enables filtering unwanted options (here: `-a` and This simple wrapper enables filtering unwanted options (here: `-a` and
`--all` for `ls`) out of the command line. It reads the positional `--all` for `ls`) out of the command line. It reads the positional
parameters and builds a filtered array consisting of them, then calls parameters and builds a filtered array consisting of them, then calls
`ls` with the new option set. It also respects the `--` as \"end of `ls` with the new option set. It also respects the `--` as "end of
options\" for `ls` and doesn't change anything after it: options" for `ls` and doesn't change anything after it:
#!/bin/bash #!/bin/bash

View File

@ -18,7 +18,7 @@ tree**. Every process has a parent process that started, or is
responsible, for it. Every process has its own **context memory** (Not responsible, for it. Every process has its own **context memory** (Not
the memory where the process stores its data, rather, the memory where the memory where the process stores its data, rather, the memory where
data is stored that doesn't directly belong to the process, but is data is stored that doesn't directly belong to the process, but is
needed to run the process) i.e. [**The environment**]{.underline}. needed to run the process) i.e. <u>**The environment**</u>.
Every process has its **own** environment space. Every process has its **own** environment space.
@ -28,7 +28,7 @@ form, but they are not related to shell variables. A variable named
`LANG`, for example, is used by every program that looks it up in its `LANG`, for example, is used by every program that looks it up in its
environment to determinate the current locale. environment to determinate the current locale.
**[Attention:]{.underline}** A variable that is set, like with <u>**Attention:**</u> A variable that is set, like with
`MYVAR=Hello`, is **not** automatically part of the environment. You `MYVAR=Hello`, is **not** automatically part of the environment. You
need to put it into the environment with the bash builtin command need to put it into the environment with the bash builtin command
`export`: `export`:
@ -41,30 +41,30 @@ set by login scripts or programs).
## Executing programs ## Executing programs
All the diagrams of the process tree use names like \"`xterm`\" or All the diagrams of the process tree use names like "`xterm`" or
\"`bash`\", but that's just to make it easier to understand what's "`bash`", but that's just to make it easier to understand what's
going on, it doesn't mean those processes are actually executed. going on, it doesn't mean those processes are actually executed.
Let's take a short look at what happens when you \"execute a program\" Let's take a short look at what happens when you "execute a program"
from the Bash prompt, a program like \"ls\": from the Bash prompt, a program like "ls":
$ ls $ ls
Bash will now perform **two steps**: Bash will now perform **two steps**:
- It will make a copy of itself - It will make a copy of itself
- The copy will replace itself with the \"ls\" program - The copy will replace itself with the "ls" program
The copy of Bash will inherit the environment from the \"main Bash\" The copy of Bash will inherit the environment from the "main Bash"
process: All environment variables will also be copied to the new process: All environment variables will also be copied to the new
process. This step is called **forking**. process. This step is called **forking**.
For a short moment, you have a process tree that might look like For a short moment, you have a process tree that might look like
this\... this...
xterm ----- bash ----- bash(copy) xterm ----- bash ----- bash(copy)
\...and after the \"second Bash\" (the copy) replaces itself with the ...and after the "second Bash" (the copy) replaces itself with the
`ls` program (the copy execs it), it might look like `ls` program (the copy execs it), it might look like
xterm ----- bash ----- ls xterm ----- bash ----- ls
@ -73,10 +73,10 @@ If everything was okay, the two steps resulted in one program being run.
The copy of the environment from the first step (forking) becomes the The copy of the environment from the first step (forking) becomes the
environment for the final running program (in this case, `ls`). environment for the final running program (in this case, `ls`).
[**What is so important about it?**]{.underline} In our example, what <u>**What is so important about it?**</u> In our example, what
the program `ls` does inside its own environment, it can't affect the the program `ls` does inside its own environment, it can't affect the
environment of its parent process (in this case, `bash`). The environment of its parent process (in this case, `bash`). The
environment was copied when ls was executed. Nothing is \"copied back\" environment was copied when ls was executed. Nothing is "copied back"
to the parent environment when `ls` terminates. to the parent environment when `ls` terminates.
## Bash playing with pipes ## Bash playing with pipes
@ -84,7 +84,7 @@ to the parent environment when `ls` terminates.
Pipes are a very powerful tool. You can connect the output of one Pipes are a very powerful tool. You can connect the output of one
process to the input of another process. We won't delve into piping at process to the input of another process. We won't delve into piping at
this point, we just want to see how it looks in the process tree. Again, this point, we just want to see how it looks in the process tree. Again,
we execute some commands, this time, we\'ll run `ls` and `grep`: we execute some commands, this time, we'll run `ls` and `grep`:
$ ls | grep myfile $ ls | grep myfile
@ -98,7 +98,7 @@ Note once again, `ls` can't influence the `grep` environment, `grep`
can't influence the `ls` environment, and neither `grep` nor `ls` can can't influence the `ls` environment, and neither `grep` nor `ls` can
influence the `bash` environment. influence the `bash` environment.
[**How is that related to shell programming?!?**]{.underline} <u>**How is that related to shell programming?!?**</u>
Well, imagine some Bash code that reads data from a pipe. For example, Well, imagine some Bash code that reads data from a pipe. For example,
the internal command `read`, which reads data from *stdin* and puts it the internal command `read`, which reads data from *stdin* and puts it
@ -120,12 +120,12 @@ it a bit, we have:
See the relationship? The forked Bash process will count the lines like See the relationship? The forked Bash process will count the lines like
a charm. It will also set the variable `counter` as directed. But if a charm. It will also set the variable `counter` as directed. But if
everything ends, this extra process will be terminated - **your everything ends, this extra process will be terminated - **your
\"counter\" variable is gone.** You see a 0 because in the main shell it "counter" variable is gone.** You see a 0 because in the main shell it
was 0, and wasn't changed by the child process! was 0, and wasn't changed by the child process!
[**So, how do we count the lines?**]{.underline} Easy: **Avoid the <u>**So, how do we count the lines?**</u> Easy: **Avoid the
subshell.** The details don't matter, the important thing is the shell subshell.** The details don't matter, the important thing is the shell
that sets the counter must be the \"main shell\". For example: that sets the counter must be the "main shell". For example:
counter=0 counter=0
@ -185,4 +185,5 @@ pipe in the command substitution:
xterm ----- bash ----- bash (cmd. subst.) --| xterm ----- bash ----- bash (cmd. subst.) --|
+-- wc -l +-- wc -l
FIXME to be continued !!! warning "FIXME"
to be continued

View File

@ -1,14 +1,15 @@
# Scripting with style # Scripting with style
FIXME continue !!! warning "FIXME"
continue
These are some coding guidelines that helped me to read and understand These are some coding guidelines that helped me to read and understand
my own code over the years. They also will help to produce code that my own code over the years. They also will help to produce code that
will be a bit more robust than \"if something breaks, I know how to fix will be a bit more robust than "if something breaks, I know how to fix
it\". it".
This is not a bible, of course. But I have seen so much ugly and This is not a bible, of course. But I have seen so much ugly and
terrible code (not only in shell) during all the years, that I\'m 100% terrible code (not only in shell) during all the years, that I'm 100%
convinced there needs to be *some* code layout and style. No matter convinced there needs to be *some* code layout and style. No matter
which one you use, use it throughout your code (at least don't change which one you use, use it throughout your code (at least don't change
it within the same shellscript file); don't change your code layout it within the same shellscript file); don't change your code layout
@ -22,7 +23,7 @@ of course it helps others to read the code.
Indentation is nothing that technically influences a script, it's only Indentation is nothing that technically influences a script, it's only
for us humans. for us humans.
I\'m used to seeing/using indentation of *two space characters* (though I'm used to seeing/using indentation of *two space characters* (though
many may prefer 4 spaces, see below in the discussion section): many may prefer 4 spaces, see below in the discussion section):
- it's easy and fast to type - it's easy and fast to type
@ -32,7 +33,7 @@ many may prefer 4 spaces, see below in the discussion section):
waste too much space on the line waste too much space on the line
Speaking of hard-tabs: Avoid them if possible. They only make trouble. I Speaking of hard-tabs: Avoid them if possible. They only make trouble. I
can imagine one case where they\'re useful: Indenting can imagine one case where they're useful: Indenting
[here-documents](../syntax/redirection.md#here_documents). [here-documents](../syntax/redirection.md#here_documents).
### Breaking up lines ### Breaking up lines
@ -40,33 +41,33 @@ can imagine one case where they\'re useful: Indenting
Whenever you need to break lines of long code, you should follow one of Whenever you need to break lines of long code, you should follow one of
these two rules: these two rules:
[**Indention using command width:**]{.underline} <u>**Indention using command width:**</u>
activate some_very_long_option \ activate some_very_long_option \
some_other_option some_other_option
[**Indention using two spaces:**]{.underline} <u>**Indention using two spaces:**</u>
activate some_very_long_option \ activate some_very_long_option \
some_other_option some_other_option
Personally, with some exceptions, I prefer the first form because it Personally, with some exceptions, I prefer the first form because it
supports the visual impression of \"these belong together\". supports the visual impression of "these belong together".
### Breaking compound commands ### Breaking compound commands
[Compound commands](../syntax/ccmd/intro.md) form the structures that make a [Compound commands](../syntax/ccmd/intro.md) form the structures that make a
shell script different from a stupid enumeration of commands. Usually shell script different from a stupid enumeration of commands. Usually
they contain a kind of \"head\" and a \"body\" that contains command they contain a kind of "head" and a "body" that contains command
lists. This type of compound command is relatively easy to indent. lists. This type of compound command is relatively easy to indent.
I\'m used to (not all points apply to all compound commands, just pick I'm used to (not all points apply to all compound commands, just pick
the basic idea): the basic idea):
- put the introducing keyword and the initial command list or - put the introducing keyword and the initial command list or
parameters on one line (\"head\") parameters on one line ("head")
- put the \"body-introducing\" keyword on the same line - put the "body-introducing" keyword on the same line
- the command list of the \"body\" on separate lines, indented by two - the command list of the "body" on separate lines, indented by two
spaces spaces
- put the closing keyword on a separated line, indented like the - put the closing keyword on a separated line, indented like the
initial introducing keyword initial introducing keyword
@ -82,7 +83,7 @@ What?! Well, here again:
##### if/then/elif/else ##### if/then/elif/else
This construct is a bit special, because it has keywords (`elif`, This construct is a bit special, because it has keywords (`elif`,
`else`) \"in the middle\". The visually appealing way is to indent them `else`) "in the middle". The visually appealing way is to indent them
like this: like this:
if ...; then if ...; then
@ -110,7 +111,7 @@ like this:
The `case` construct might need a bit more discussion here, since its The `case` construct might need a bit more discussion here, since its
structure is a bit more complex. structure is a bit more complex.
In general, every new \"layer\" gets a new indentation level: In general, every new "layer" gets a new indentation level:
case $input in case $input in
hello) hello)
@ -149,13 +150,13 @@ It's - just like in C - the middle ground between smart, efficient and
readable. readable.
If you need to use a cryptic construct, include a comment that explains If you need to use a cryptic construct, include a comment that explains
what your \"monster\" does. what your "monster" does.
### Variable names ### Variable names
Since all reserved variables are `UPPERCASE`, the safest way is to only Since all reserved variables are `UPPERCASE`, the safest way is to only
use `lowercase` variable names. This is true for reading user input, use `lowercase` variable names. This is true for reading user input,
loop counting variables, etc., \... (in the example: `file`) loop counting variables, etc., ... (in the example: `file`)
- prefer `lowercase` variables - prefer `lowercase` variables
- if you use `UPPERCASE` names, **do not use reserved variable names** - if you use `UPPERCASE` names, **do not use reserved variable names**
@ -165,9 +166,6 @@ loop counting variables, etc., \... (in the example: `file`)
- if you use `UPPERCASE` names, prepend the name with a unique prefix - if you use `UPPERCASE` names, prepend the name with a unique prefix
(`MY_` in the example below) (`MY_` in the example below)
```{=html}
<!-- -->
```
#!/bin/bash #!/bin/bash
# the prefix 'MY_' # the prefix 'MY_'
@ -200,7 +198,7 @@ in-code documentation for them.
### Parameter expansion ### Parameter expansion
Unless you are really sure what you\'re doing, **quote every parameter Unless you are really sure what you're doing, **quote every parameter
expansion**. expansion**.
There are some cases where this isn't needed from a technical point of There are some cases where this isn't needed from a technical point of
@ -212,7 +210,7 @@ view, e.g.
- variable assignment: `VAR=$WORD` - variable assignment: `VAR=$WORD`
But quoting these is never a mistake. If you quote every parameter But quoting these is never a mistake. If you quote every parameter
expansion, you\'ll be safe. expansion, you'll be safe.
If you need to parse a parameter as a list of words, you can't quote, If you need to parse a parameter as a list of words, you can't quote,
of course, e.g. of course, e.g.
@ -252,8 +250,8 @@ should quote the command substitution!
### Eval ### Eval
Well, like Greg says: **\"If eval is the answer, surely you are asking Well, like Greg says: **"If eval is the answer, surely you are asking
the wrong question.\"** the wrong question."**
Avoid it, unless absolutely neccesary: Avoid it, unless absolutely neccesary:
@ -262,7 +260,7 @@ Avoid it, unless absolutely neccesary:
- if possible, re-think the way your script works, if it seems you - if possible, re-think the way your script works, if it seems you
can't avoid `eval` with your current method can't avoid `eval` with your current method
- if you really, really, have to use it, then take care, and be sure - if you really, really, have to use it, then take care, and be sure
about what you\'re doing about what you're doing
## Basic structure ## Basic structure
@ -281,8 +279,8 @@ The basic structure of a script simply reads:
If possible (I know it's not always possible!), use a If possible (I know it's not always possible!), use a
[shebang](../dict/interpreter_directive.md). [shebang](../dict/interpreter_directive.md).
Be careful with `/bin/sh`: The argument that \"on Linux `/bin/sh` is Be careful with `/bin/sh`: The argument that "on Linux `/bin/sh` is
Bash\" **is a lie** (and technically irrelevant) Bash" **is a lie** (and technically irrelevant)
The shebang serves two purposes for me: The shebang serves two purposes for me:
@ -290,16 +288,16 @@ The shebang serves two purposes for me:
called directly: If you code for Bash, specify `bash`! called directly: If you code for Bash, specify `bash`!
- it documents the desired interpreter (so: use `bash` when you write - it documents the desired interpreter (so: use `bash` when you write
a Bash-script, use `sh` when you write a general Bourne/POSIX a Bash-script, use `sh` when you write a general Bourne/POSIX
script, \...) script, ...)
### Configuration variables ### Configuration variables
I call variables that are meant to be changed by the user I call variables that are meant to be changed by the user
\"configuration variables\" here. "configuration variables" here.
Make them easy to find (directly at the top of the script), give them Make them easy to find (directly at the top of the script), give them
meaningful names and maybe a short comment. As noted above, use meaningful names and maybe a short comment. As noted above, use
`UPPERCASE` for them only when you\'re sure about what you\'re doing. `UPPERCASE` for them only when you're sure about what you're doing.
`lowercase` will be the safest. `lowercase` will be the safest.
### Function definitions ### Function definitions
@ -310,7 +308,7 @@ overview and ensures that all function names are known before they are
used. used.
Since a function isn't parsed before it is executed, you usually don't Since a function isn't parsed before it is executed, you usually don't
have to ensure they\'re in a specific order. have to ensure they're in a specific order.
The portable form of the function definition should be used, without the The portable form of the function definition should be used, without the
`function` keyword (here using the [grouping compound `function` keyword (here using the [grouping compound
@ -336,7 +334,7 @@ begins its work in a potentially broken state.
### Availability of commands ### Availability of commands
If you use external commands that may not be present on the path, or not If you use external commands that may not be present on the path, or not
installed, check for their availability, then tell the user they\'re installed, check for their availability, then tell the user they're
missing. missing.
Example: Example:
@ -370,9 +368,9 @@ means:
This, **and only this**, will enable the calling component to check the This, **and only this**, will enable the calling component to check the
operation status of your script. operation status of your script.
You know: **\"One of the main causes of the fall of the Roman Empire was You know: **"One of the main causes of the fall of the Roman Empire was
that, lacking zero, they had no way to indicate successful termination that, lacking zero, they had no way to indicate successful termination
of their C programs.\"** *-- Robert Firth* of their C programs."** *-- Robert Firth*
## Misc ## Misc
@ -405,5 +403,5 @@ of their C programs.\"** *-- Robert Firth*
### Tooling ### Tooling
- some of these guidelines, such as indentation, positioning of - some of these guidelines, such as indentation, positioning of
\"body-introducing\" keywords, and portable function declarations, "body-introducing" keywords, and portable function declarations,
can be enforced by [shfmt](https://github.com/mvdan/sh) can be enforced by [shfmt](https://github.com/mvdan/sh)

View File

@ -23,8 +23,8 @@ printed (like any other text). If the terminal understands the code, it
won't display the character-sequence, but will perform some action. You won't display the character-sequence, but will perform some action. You
can print the codes with a simple `echo` command. can print the codes with a simple `echo` command.
[**Note:**]{.underline} I see codes referenced as \"Bash colors\" <u>**Note:**</u> I see codes referenced as "Bash colors"
sometimes (several \"Bash tutorials\" etc\...): That's a completely sometimes (several "Bash tutorials" etc...): That's a completely
incorrect definition. incorrect definition.
## The tput command ## The tput command
@ -43,7 +43,7 @@ understands).
## The codes ## The codes
In this list I\'ll focus on ANSI/VT100 control codes for the most common In this list I'll focus on ANSI/VT100 control codes for the most common
actions - take it as quick reference. The documentation of your terminal actions - take it as quick reference. The documentation of your terminal
or the `terminfo` database is always the preferred source when something or the `terminfo` database is always the preferred source when something
is unclear! Also the `tput` acronyms are usually the ones dedicated for is unclear! Also the `tput` acronyms are usually the ones dedicated for
@ -53,7 +53,7 @@ I listed only the most relevant codes, of course, any ANSI terminal
understands many more! But let's keep the discussion centered on common understands many more! But let's keep the discussion centered on common
shell scripting ;-) shell scripting ;-)
If I couldn't find a matching ANSI escape, you\'ll see a :?: as the If I couldn't find a matching ANSI escape, you'll see a :?: as the
code. Feel free to mail me or fix it. code. Feel free to mail me or fix it.
The ANSI codes always start with the ESC character. (ASCII 0x1B or octal The ANSI codes always start with the ESC character. (ASCII 0x1B or octal
@ -63,29 +63,29 @@ codes directly - use the `tput` command!**
All codes that can be used with `tput` can be found in terminfo(5). (on All codes that can be used with `tput` can be found in terminfo(5). (on
OpenBSD at least) See [OpenBSD's OpenBSD at least) See [OpenBSD's
terminfo(5)](http://www.openbsd.org/cgi-bin/man.cgi?query=terminfo&apropos=0&sektion=5&manpath=OpenBSD+Current&arch=i386&format=html) terminfo(5)](http://www.openbsd.org/cgi-bin/man.cgi?query=terminfo&apropos=0&sektion=5&manpath=OpenBSD+Current&arch=i386&format=html)
under the [Capabilities]{.underline} section. The *cap-name* is the code under the <u>Capabilities</u> section. The *cap-name* is the code
to use with tput. A description of each code is also provided. to use with tput. A description of each code is also provided.
### General useful ASCII codes ### General useful ASCII codes
The **Ctrl-Key** representation is simply associating the non-printable The **Ctrl-Key** representation is simply associating the non-printable
characters from ASCII code 1 with the printable (letter) characters from characters from ASCII code 1 with the printable (letter) characters from
ASCII code 65 (\"A\"). ASCII code 1 would be `^A` (Ctrl-A), while ASCII ASCII code 65 ("A"). ASCII code 1 would be `^A` (Ctrl-A), while ASCII
code 7 (BEL) would be `^G` (Ctrl-G). This is a common representation code 7 (BEL) would be `^G` (Ctrl-G). This is a common representation
(and input method) and historically comes from one of the VT series of (and input method) and historically comes from one of the VT series of
terminals. terminals.
Name decimal octal hex C-escape Ctrl-Key Description |Name|decimal|octal|hex|C-escape|Ctrl-Key|Description|
------- --------- ------- ------ ---------- ---------- -------------------------------- |-------|---------|-------|------|----------|----------|--------------------------------|
`BEL` 7 007 0x07 `\a` `^G` Terminal bell |`BEL`|7|007|0x07|`\a`|`^G`|Terminal bell|
`BS` 8 010 0x08 `\b` `^H` Backspace |`BS`|8|010|0x08|`\b`|`^H`|Backspace|
`HT` 9 011 0x09 `\t` `^I` Horizontal TAB |`HT`|9|011|0x09|`\t`|`^I`|Horizontal TAB|
`LF` 10 012 0x0A `\n` `^J` Linefeed (newline) |`LF`|10|012|0x0A|`\n`|`^J`|Linefeed (newline)|
`VT` 11 013 0x0B `\v` `^K` Vertical TAB |`VT`|11|013|0x0B|`\v`|`^K`|Vertical TAB|
`FF` 12 014 0x0C `\f` `^L` Formfeed (also: New page `NP`) |`FF`|12|014|0x0C|`\f`|`^L`|Formfeed (also: New page `NP`)|
`CR` 13 015 0x0D `\r` `^M` Carriage return |`CR`|13|015|0x0D|`\r`|`^M`|Carriage return|
`ESC` 27 033 0x1B `<none>` `^[` Escape character |`ESC`|27|033|0x1B|`<none>`|`^[`|Escape character|
`DEL` 127 177 0x7F `<none>` `<none>` Delete character |`DEL`|127|177|0x7F|`<none>`|`<none>`|Delete character|
### Cursor handling ### Cursor handling
@ -114,7 +114,7 @@ terminals.
ANSI terminfo equivalent Description ANSI terminfo equivalent Description
--------- --------------------- ---------------------------------------------------------------- --------- --------------------- ----------------------------------------------------------------
`[ K`\ `el` **Clear line** from current cursor position **to end** of line `[ K`\ `el` **Clear line** from current cursor position **to end** of line
`[ 0 K` `[ 0 K`
`[ 1 K` `el1` **Clear line from beginning** to current cursor position `[ 1 K` `el1` **Clear line from beginning** to current cursor position
@ -123,44 +123,43 @@ terminals.
### General text attributes ### General text attributes
ANSI terminfo equivalent Description |ANSI|terminfo equivalent|Description|
--------- ----------------------------- ------------------------------------------------ |----|-------------------|-----------|
`[ 0 m` `sgr0` Reset all attributes |`[ 0 m`|`sgr0`|Reset all attributes|
`[ 1 m` `bold` Set \"bright\" attribute |`[ 1 m`|`bold`|Set "bright" attribute|
`[ 2 m` `dim` Set \"dim\" attribute |`[ 2 m`|`dim`|Set "dim" attribute|
`[ 3 m` `smso` Set \"standout\" attribute |`[ 3 m`|`smso`|Set "standout" attribute|
`[ 4 m` set `smul` unset `rmul` :?: Set \"underscore\" (underlined text) attribute |`[ 4 m`|set `smul` unset `rmul` :?:|Set "underscore" (underlined text) attribute|
`[ 5 m` `blink` Set \"blink\" attribute |`[ 5 m`|`blink`|Set "blink" attribute|
`[ 7 m` `rev` Set \"reverse\" attribute |`[ 7 m`|`rev`|Set "reverse" attribute|
`[ 8 m` `invis` Set \"hidden\" attribute |`[ 8 m`|`invis`|Set "hidden" attribute|
### Foreground coloring ### Foreground coloring
ANSI terminfo equivalent Description |ANSI|terminfo equivalent|Description|
----------- --------------------- ---------------------------------------------- |----|-------------------|-----------|
`[ 3 0 m` `setaf 0` Set **foreground** to color #0 - **black** |`[ 3 0 m`|`setaf 0`|Set **foreground** to color \#0 - **black**|
`[ 3 1 m` `setaf 1` Set **foreground** to color #1 - **red** |`[ 3 1 m`|`setaf 1`|Set **foreground** to color \#1 - **red**|
`[ 3 2 m` `setaf 2` Set **foreground** to color #2 - **green** |`[ 3 2 m`|`setaf 2`|Set **foreground** to color \#2 - **green**|
`[ 3 3 m` `setaf 3` Set **foreground** to color #3 - **yellow** |`[ 3 3 m`|`setaf 3`|Set **foreground** to color \#3 - **yellow**|
`[ 3 4 m` `setaf 4` Set **foreground** to color #4 - **blue** |`[ 3 4 m`|`setaf 4`|Set **foreground** to color \#4 - **blue**|
`[ 3 5 m` `setaf 5` Set **foreground** to color #5 - **magenta** |`[ 3 5 m`|`setaf 5`|Set **foreground** to color \#5 - **magenta**|
`[ 3 6 m` `setaf 6` Set **foreground** to color #6 - **cyan** |`[ 3 6 m`|`setaf 6`|Set **foreground** to color \#6 - **cyan**|
`[ 3 7 m` `setaf 7` Set **foreground** to color #7 - **white** |`[ 3 7 m`|`setaf 7`|Set **foreground** to color \#7 - **white**|
`[ 3 9 m` `setaf 9` Set **default** color as foreground color |`[ 3 9 m`|`setaf 9`|Set **default** color as foreground color|
### Background coloring ### Background coloring
ANSI terminfo equivalent Description |ANSI|terminfo equivalent|Description|
----------- --------------------- ---------------------------------------------- |----|-------------------|-----------|
`[ 4 0 m` `setab 0` Set **background** to color #0 - **black** |`[ 4 0 m`|`setab 0`|Set **background** to color \#0 - **black**|
`[ 4 1 m` `setab 1` Set **background** to color #1 - **red** |`[ 4 1 m`|`setab 1`|Set **background** to color \#1 - **red**|
`[ 4 2 m` `setab 2` Set **background** to color #2 - **green** |`[ 4 2 m`|`setab 2`|Set **background** to color \#2 - **green**|
`[ 4 3 m` `setab 3` Set **background** to color #3 - **yellow** |`[ 4 3 m`|`setab 3`|Set **background** to color \#3 - **yellow**|
`[ 4 4 m` `setab 4` Set **background** to color #4 - **blue** |`[ 4 4 m`|`setab 4`|Set **background** to color \#4 - **blue**|
`[ 4 5 m` `setab 5` Set **background** to color #5 - **magenta** |`[ 4 5 m`|`setab 5`|Set **background** to color \#5 - **magenta**|
`[ 4 6 m` `setab 6` Set **background** to color #6 - **cyan** |`[ 4 6 m`|`setab 6`|Set **background** to color \#6 - **cyan**|
`[ 4 7 m` `setab 7` Set **background** to color #7 - **white** |`[ 4 7 m`|`setab 7`|Set **background** to color \#7 - **white**|
`[ 4 9 m` `setab 9` Set **default** color as background color |`[ 4 9 m`|`setab 9`|Set **default** color as background color|
### Misc codes ### Misc codes
@ -168,7 +167,7 @@ terminals.
Used capabilities: `smcup`, `rmcup` Used capabilities: `smcup`, `rmcup`
You\'ve undoubtedly already encountered programs that restore the You've undoubtedly already encountered programs that restore the
terminal contents after they do their work (like `vim`). This can be terminal contents after they do their work (like `vim`). This can be
done by the following commands: done by the following commands:
@ -187,7 +186,7 @@ These features require that certain capabilities exist in your
termcap/terminfo. While `xterm` and most of its clones (`rxvt`, `urxvt`, termcap/terminfo. While `xterm` and most of its clones (`rxvt`, `urxvt`,
etc) will support the instructions, your operating system may not etc) will support the instructions, your operating system may not
include references to them in its default xterm profile. (FreeBSD, in include references to them in its default xterm profile. (FreeBSD, in
particular, falls into this category.) If \`tput smcup\` appears to do particular, falls into this category.) If `tput smcup` appears to do
nothing for you, and you don't want to modify your system nothing for you, and you don't want to modify your system
termcap/terminfo data, and you KNOW that you are using a compatible termcap/terminfo data, and you KNOW that you are using a compatible
xterm application, the following may work for you: xterm application, the following may work for you:
@ -198,14 +197,14 @@ xterm application, the following may work for you:
Certain software uses these codes (via their termcap capabilities) as Certain software uses these codes (via their termcap capabilities) as
well. You may have seen the screen save/restore in `less`, `vim`, `top`, well. You may have seen the screen save/restore in `less`, `vim`, `top`,
`screen` and others. Some of these applications may also provide `screen` and others. Some of these applications may also provide
configuration options to \*disable\* this behaviour. For example, `less` configuration options to *disable* this behaviour. For example, `less`
has a `-X` option for this, which can also be set in an environment has a `-X` option for this, which can also be set in an environment
variable: variable:
export LESS=X export LESS=X
less /path/to/file less /path/to/file
Similarly, `vim` can be configured not to \"restore\" the screen by Similarly, `vim` can be configured not to "restore" the screen by
adding the following to your `~/.vimrc`: adding the following to your `~/.vimrc`:
set t_ti= t_te= set t_ti= t_te=
@ -226,7 +225,7 @@ in graphical environments.
The Virtual Terminal implemented in the Linux kernel supports only 16 The Virtual Terminal implemented in the Linux kernel supports only 16
colors, and the usual default terminfo entry for `TERM=linux` defines colors, and the usual default terminfo entry for `TERM=linux` defines
only 8. There is sometimes an alternate \"linux-16color\" that you can only 8. There is sometimes an alternate "linux-16color" that you can
switch to, to get the other 8 colors. switch to, to get the other 8 colors.
## Bash examples ## Bash examples
@ -237,11 +236,11 @@ switch to, to get the other 8 colors.
### Colors using tput ### Colors using tput
[Directly inside the echo:]{.underline} <u>Directly inside the echo:</u>
echo "TPUT is a $(tput setaf 2)nice$(tput setaf 9) and $(tput setaf 5)user friendly$(tput setaf 9) terminal capability database." echo "TPUT is a $(tput setaf 2)nice$(tput setaf 9) and $(tput setaf 5)user friendly$(tput setaf 9) terminal capability database."
[With preset variables:]{.underline} <u>With preset variables:</u>
COL_NORM="$(tput setaf 9)" COL_NORM="$(tput setaf 9)"
COL_RED="$(tput setaf 1)" COL_RED="$(tput setaf 1)"
@ -250,7 +249,7 @@ switch to, to get the other 8 colors.
### Misc ### Misc
[HOME function]{.underline} <u>HOME function</u>
home() { home() {
# yes, actually not much shorter ;-) # yes, actually not much shorter ;-)
@ -323,7 +322,7 @@ default), but uses only features that don't make the Bash parser crash.
# Combined Bash/ksh93 flavors by Dan Douglas (ormaaj) # Combined Bash/ksh93 flavors by Dan Douglas (ormaaj)
function doBash { function doBash {
typeset P Q X Y a b c i v x y typeset P Q X Y a b c i v x y
for ((P=10**8,Q=P/100,X=320*Q/cols,Y=210*Q/lines,y=-105*Q,v=-220*Q,x=v;y<105*Q;x=v,y+=Y)); do for ((P=10**8,Q=P/100,X=320*Q/cols,Y=210*Q/lines,y=-105*Q,v=-220*Q,x=v;y<105*Q;x=v,y+=Y)); do
for ((;x<P;a=b=i=c=0,x+=X)); do for ((;x<P;a=b=i=c=0,x+=X)); do
for ((;a**2+b**2<4*P**2&&i++<99;a=((c=a)**2-b**2)/P+x,b=2*c*b/P+y)); do : for ((;a**2+b**2<4*P**2&&i++<99;a=((c=a)**2-b**2)/P+x,b=2*c*b/P+y)); do :
@ -336,14 +335,14 @@ default), but uses only features that don't make the Bash parser crash.
function doKsh { function doKsh {
integer i integer i
float a b c x=2.2 y=-1.05 X=3.2/cols Y=2.1/lines float a b c x=2.2 y=-1.05 X=3.2/cols Y=2.1/lines
while while
for ((a=b=i=0;(c=a)**2+b**2<=2&&i++<99&&(a=a**2-b**2+x,b=2*c*b+y);)); do : for ((a=b=i=0;(c=a)**2+b**2<=2&&i++<99&&(a=a**2-b**2+x,b=2*c*b+y);)); do :
done done
. colorBox $((i<99?i%16:0)) . colorBox $((i<99?i%16:0))
if ((x<1?!(x+=X):(y+=Y,x=-2.2))); then if ((x<1?!(x+=X):(y+=Y,x=-2.2))); then
print print
((y<1.05)) ((y<1.05))
fi fi
do : do :
done done

View File

@ -16,7 +16,7 @@ This example queries the hostkeys for the very same machine, but under 3
different \"names\" (hostname, FQDN, IP) and redirects the output to the different \"names\" (hostname, FQDN, IP) and redirects the output to the
`known_hosts`-file. `known_hosts`-file.
[**Notes:**]{.underline} <u>**Notes:**</u>
- if done blindly, the `known_host`-file may grow very large. It might - if done blindly, the `known_host`-file may grow very large. It might
be wise to check for key existance first be wise to check for key existance first

View File

@ -31,7 +31,7 @@ then this script should generate code that looks like
you need correct escapes or quotes to not generate shell special you need correct escapes or quotes to not generate shell special
characters out of normal text (like embedded dollar signs `$`). characters out of normal text (like embedded dollar signs `$`).
**[Solution:]{.underline}** **<u>Solution:</u>**
A loop over the own arguments that writes out properly quoted/escaped A loop over the own arguments that writes out properly quoted/escaped
code to the generated script file code to the generated script file
@ -67,7 +67,7 @@ The generated script will look like:
#!/bin/bash #!/bin/bash
echo 'fir$t' 'seco "ond"' 'thir'\''d' echo 'fir$t' 'seco "ond"' 'thir'\''d'
## Using printf ## Using printf
@ -90,4 +90,4 @@ The generated script will look like:
#!/bin/bash #!/bin/bash
echo fir\$t seco\ \"ond\" thir\'d echo fir\$t seco\ \"ond\" thir\'d

View File

@ -74,7 +74,7 @@ When no base is specified, the base 10 (decimal) is assumed, except when
the prefixes as mentioned above (octals, hexadecimals) are present. The the prefixes as mentioned above (octals, hexadecimals) are present. The
specified base can range from 2 to 64. To represent digits in a specified base can range from 2 to 64. To represent digits in a
specified base greater than 10, characters other than 0 to 9 are needed specified base greater than 10, characters other than 0 to 9 are needed
(in this order, low => high): (in this order, low =&gt; high):
- `0 ... 9` - `0 ... 9`
- `a ... z` - `a ... z`
@ -124,8 +124,8 @@ named parameters, e.g.:
# will output "3"! # will output "3"!
Of course, in the end, when it finally evaluates to something that is Of course, in the end, when it finally evaluates to something that is
**not** a valid arithmetic expression (newlines, ordinary text, \...) **not** a valid arithmetic expression (newlines, ordinary text, ...)
then you\'ll get an error. then you'll get an error.
When variables are referenced, the notation `1 + $X` is equivalent to When variables are referenced, the notation `1 + $X` is equivalent to
the notation `1 + X`, both are allowed. the notation `1 + X`, both are allowed.
@ -138,10 +138,10 @@ an arithmetic expression.
## Truth ## Truth
Unlike command exit and return codes, arithmetic expressions evaluate to Unlike command exit and return codes, arithmetic expressions evaluate to
logical \"true\" when they are not 0. When they are 0, they evaluate to logical "true" when they are not 0. When they are 0, they evaluate to
\"false\". The [arithmetic evaluation compound "false". The [arithmetic evaluation compound
command](../syntax/ccmd/arithmetic_eval.md) reverses the \"truth\" of an command](../syntax/ccmd/arithmetic_eval.md) reverses the "truth" of an
arithmetic expression to match the \"truth\" of command exit codes: arithmetic expression to match the "truth" of command exit codes:
- if the arithmetic expression brings up a value not 0 (arithmetic - if the arithmetic expression brings up a value not 0 (arithmetic
true), it returns 0 (shell true) true), it returns 0 (shell true)
@ -160,89 +160,79 @@ That means, the following `if`-clause will execute the `else`-thread:
### Assignment ### Assignment
Operator Description |Operator|Description|
--------------------- ---------------------------------------------------------------------------------------------------- |--------|-----------|
`<ID> = <EXPR>` normal assignment |`<ID> = <EXPR>`|normal assignment|
`<ID> *= <EXPR>` equivalent to `<ID> = <ID> * <EXPR>`, see [calculation operators](../syntax/arith_expr.md#calculations) |`<ID> *= <EXPR>`|equivalent to `<ID> = <ID> * <EXPR>`, see [calculation operators](../syntax/arith_expr.md#calculations)|
`<ID> /= <EXPR>` equivalent to `<ID> = <ID> / <EXPR>`, see [calculation operators](../syntax/arith_expr.md#calculations) |`<ID> /= <EXPR>`|equivalent to `<ID> = <ID> / <EXPR>`, see [calculation operators](../syntax/arith_expr.md#calculations)|
`<ID> %= <EXPR>` equivalent to `<ID> = <ID> % <EXPR>`, see [calculation operators](../syntax/arith_expr.md#calculations) |`<ID> %= <EXPR>`|equivalent to `<ID> = <ID> % <EXPR>`, see [calculation operators](../syntax/arith_expr.md#calculations)|
`<ID> += <EXPR>` equivalent to `<ID> = <ID> + <EXPR>`, see [calculation operators](../syntax/arith_expr.md#calculations) |`<ID> += <EXPR>`|equivalent to `<ID> = <ID> + <EXPR>`, see [calculation operators](../syntax/arith_expr.md#calculations)|
`<ID> -= <EXPR>` equivalent to `<ID> = <ID> - <EXPR>`, see [calculation operators](../syntax/arith_expr.md#calculations) |`<ID> -= <EXPR>`|equivalent to `<ID> = <ID> - <EXPR>`, see [calculation operators](../syntax/arith_expr.md#calculations)|
`<ID> <<= <NUMBER>` equivalent to `<ID> = <ID> << <NUMBER>`, see [bit operations](../syntax/arith_expr.md#bit_operations) |`<ID> <<= <NUMBER>`|equivalent to `<ID> = <ID> << <NUMBER>`, see [bit operations](../syntax/arith_expr.md#bit_operations)|
`<ID> >>= <NUMBER>` equivalent to `<ID> = <ID> >> <NUMBER>`, see [bit operations](../syntax/arith_expr.md#bit_operations) |`<ID> >>= <NUMBER>`|equivalent to `<ID> = <ID> >> <NUMBER>`, see [bit operations](../syntax/arith_expr.md#bit_operations)|
`<ID> &= <EXPR>` equivalent to `<ID> = <ID> & <EXPR>`, see [bit operations](../syntax/arith_expr.md#bit_operations) |`<ID> &= <EXPR>`|equivalent to `<ID> = <ID> & <EXPR>`, see [bit operations](../syntax/arith_expr.md#bit_operations)|
`<ID> ^= <EXPR>` equivalent to `<ID> = <ID> ^ <EXPR>`, see [bit operations](../syntax/arith_expr.md#bit_operations) |`<ID> ^= <EXPR>`|equivalent to `<ID> = <ID> ^ <EXPR>`, see [bit operations](../syntax/arith_expr.md#bit_operations)|
`<ID> |= <EXPR>` equivalent to `<ID> = <ID> | <EXPR>`, see [bit operations](../syntax/arith_expr.md#bit_operations) |`<ID>|= <EXPR>`|equivalent to `<ID> = <ID>|<EXPR>`, see [bit operations](../syntax/arith_expr.md#bit_operations)|
### Calculations ### Calculations
Operator Description |Operator|Description|
---------- -------------------- |--------|-----------|
`*` multiplication |`*`|multiplication|
`/` division |`/`|division|
`%` remainder (modulo) |`%`|remainder (modulo)|
`+` addition |`+`|addition|
`-` subtraction |`-`|subtraction|
`**` exponentiation |`**`|exponentiation|
### Comparisons ### Comparisons
Operator Description |Operator|Description|
---------- ----------------------------------- |--------|-----------|
`<` comparison: less than |`<`|comparison: less than|
`>` comparison: greater than |`>`|comparison: greater than|
`<=` comparison: less than or equal |`<=`|comparison: less than or equal|
`>=` comparison: greater than or equal |`>=`|comparison: greater than or equal|
`==` equality |`==`|equality|
`!=` inequality |`!=`|inequality|
### Bit operations ### Bit operations
Operator Description |Operator|Description|
---------- ---------------------------- |--------|-----------|
`~` bitwise negation |`~`|bitwise negation|
`<<` bitwise shifting (left) |`<<`|bitwise shifting (left)|
`>>` bitwise shifting (right) |`>>`|bitwise shifting (right)|
`&` bitwise AND |`&`|bitwise AND|
`^` bitwise exclusive OR (XOR) |`^`|bitwise exclusive OR (XOR)|
`|` bitwise OR |`|`|bitwise OR|
### Logical ### Logical
Operator Description |Operator|Description|
---------- ------------------ |--------|-----------|
`!` logical negation |`!`|logical negation|
`&&` logical AND |`&&`|logical AND|
`||` logical OR |`||`|logical OR|
### Misc ### Misc
------------------------------------------------------------------------------------------------- |Operator|Description|
Operator Description |--------|-----------|
---------------------------- -------------------------------------------------------------------- |`id++`|**post-increment** of the variable `id` (not required by POSIX(r))|
`id++` **post-increment** of the variable `id` (not required by POSIX(r)) |`id--`|**post-decrement** of the variable `id` (not required by POSIX(r))|
|`++id`|**pre-increment** of the variable `id` (not required by POSIX(r))|
`id--` **post-decrement** of the variable `id` (not required by POSIX(r)) |`--id`|**pre-decrement** of the variable `id` (not required by POSIX(r))|
|`+`|unary plus|
`++id` **pre-increment** of the variable `id` (not required by POSIX(r)) |`-`|unary minus|
|`<EXPR> ? <EXPR> : <EXPR>`|conditional (ternary) operator &lt;condition&gt; ? &lt;result-if-true&gt; : &lt;result-if-false&gt;|
`--id` **pre-decrement** of the variable `id` (not required by POSIX(r)) |`<EXPR> , <EXPR>`|expression list|
|`( <EXPR> )`|subexpression (to force precedence)|
`+` unary plus
`-` unary minus
`<EXPR> ? <EXPR> : <EXPR>` conditional (ternary) operator\
<condition> ? <result-if-true> : <result-if-false>
`<EXPR> , <EXPR>` expression list
`( <EXPR> )` subexpression (to force precedence)
-------------------------------------------------------------------------------------------------
## Precedence ## Precedence
The operator precedence is as follows (highest -> lowest): The operator precedence is as follows (highest -&gt; lowest):
- Postfix (`id++`, `id--`) - Postfix (`id++`, `id--`)
- Prefix (`++id`, `--id`) - Prefix (`++id`, `--id`)
@ -274,19 +264,19 @@ Bash's overall language construct is based on exit codes or return
codes of commands or functions to be executed. `if` statements, `while` codes of commands or functions to be executed. `if` statements, `while`
loops, etc., they all take the return codes of commands as conditions. loops, etc., they all take the return codes of commands as conditions.
Now the problem is: The return codes (0 means \"TRUE\" or \"SUCCESS\", Now the problem is: The return codes (0 means "TRUE" or "SUCCESS",
not 0 means \"FALSE\" or \"FAILURE\") don't correspond to the meaning not 0 means "FALSE" or "FAILURE") don't correspond to the meaning
of the result of an arithmetic expression (0 means \"FALSE\", not 0 of the result of an arithmetic expression (0 means "FALSE", not 0
means \"TRUE\"). means "TRUE").
That's why all commands and keywords that do arithmetic operations That's why all commands and keywords that do arithmetic operations
attempt to **translate** the arithmetical meaning into an equivalent attempt to **translate** the arithmetical meaning into an equivalent
return code. This simply means: return code. This simply means:
- if the arithmetic operation evaluates to 0 (\"FALSE\"), the return - if the arithmetic operation evaluates to 0 ("FALSE"), the return
code is not 0 (\"FAILURE\") code is not 0 ("FAILURE")
- if the arithmetic operation evaluates to 1 (\"TRUE\"), the return - if the arithmetic operation evaluates to 1 ("TRUE"), the return
code is 0 (\"SUCCESS\") code is 0 ("SUCCESS")
This way, you can easily use arithmetic expressions (along with the This way, you can easily use arithmetic expressions (along with the
commands or keywords that operate them) as conditions for `if`, `while` commands or keywords that operate them) as conditions for `if`, `while`
@ -302,47 +292,48 @@ else
fi fi
``` ```
<WRAP center round important> Beware that `set -e` can change the !!! warning "Beware that `set -e` can change the runtime behavior of scripts."
runtime behavior of scripts. For example,
This non-equivalence of code behavior deserves some attention. Consider For example,
what happens if v happens to be zero in the expression below:
``` bash This non-equivalence of code behavior deserves some attention. Consider
((v += 0)) what happens if v happens to be zero in the expression below:
echo $?
```
1 ``` bash
((v += 0))
echo $?
```
(\"FAILURE\") 1
``` bash ("FAILURE")
v=$((v + 0))
echo $?
```
0 ``` bash
v=$((v + 0))
echo $?
```
(\"SUCCESS\") 0
The return code behavior is not equivalent to the arithmetic behavior, ("SUCCESS")
as has been noted.
A workaround is to use a list operation that returns True, or use the The return code behavior is not equivalent to the arithmetic behavior,
second assignment style. as has been noted.
``` bash A workaround is to use a list operation that returns True, or use the
((v += 0)) || : second assignment style.
echo $?
```
0 ``` bash
((v += 0)) || :
echo $?
```
(\"SUCCESS\") 0
This change in code behavior was discovered once the script was run ("SUCCESS")
under set -e. </WRAP>
This change in code behavior was discovered once the script was run
under set -e.
## Arithmetic expressions in Bash ## Arithmetic expressions in Bash
@ -350,4 +341,4 @@ under set -e. </WRAP>
- [Arithmetic expansion](../syntax/expansion/arith.md) - [Arithmetic expansion](../syntax/expansion/arith.md)
- [Arithmetic evaluation compound - [Arithmetic evaluation compound
command](../syntax/ccmd/arithmetic_eval.md) command](../syntax/ccmd/arithmetic_eval.md)
- [The \"let\" builtin command](../commands/builtin/let.md) - [The "let" builtin command](../commands/builtin/let.md)

View File

@ -38,7 +38,7 @@ Bash supports two different types of ksh-like one-dimensional arrays.
ksh88. Similar, partially compatible syntax was inherited by many ksh88. Similar, partially compatible syntax was inherited by many
derivatives including Bash. Indexed arrays always carry the `-a` derivatives including Bash. Indexed arrays always carry the `-a`
attribute. attribute.
- *Associative arrays* (sometimes known as a \"hash\" or \"dict\") use - *Associative arrays* (sometimes known as a "hash" or "dict") use
arbitrary nonempty strings as keys. In other words, associative arbitrary nonempty strings as keys. In other words, associative
arrays allow you to look up a value from a table based upon its arrays allow you to look up a value from a table based upon its
corresponding string label. **Associative arrays are always corresponding string label. **Associative arrays are always
@ -99,12 +99,12 @@ an array without assigning any values (see [declaration](#Declaration)).
The following explicitly give variables array attributes, making them The following explicitly give variables array attributes, making them
arrays: arrays:
Syntax Description |Syntax|Description|
-------------------- ------------------------------------------------------------------------------------------------------------------------- |------|-----------|
`ARRAY=()` Declares an **indexed** array `ARRAY` and initializes it to be empty. This can also be used to empty an existing array. |`ARRAY=()`|Declares an **indexed** array `ARRAY` and initializes it to be empty. This can also be used to empty an existing array.|
`ARRAY[0]=` Generally sets the first element of an **indexed** array. If no array `ARRAY` existed before, it is created. |`ARRAY[0]=`|Generally sets the first element of an **indexed** array. If no array `ARRAY` existed before, it is created.|
`declare -a ARRAY` Declares an **indexed** array `ARRAY`. An existing array is not initialized. |`declare -a ARRAY`|Declares an **indexed** array `ARRAY`. An existing array is not initialized.|
`declare -A ARRAY` Declares an **associative** array `ARRAY`. This is the one and only way to create associative arrays. |`declare -A ARRAY`|Declares an **associative** array `ARRAY`. This is the one and only way to create associative arrays.|
As an example, and for use below, let's declare our `NAMES` array as As an example, and for use below, let's declare our `NAMES` array as
described [above](#purpose): described [above](#purpose):
@ -116,31 +116,32 @@ described [above](#purpose):
Storing values in arrays is quite as simple as storing values in normal Storing values in arrays is quite as simple as storing values in normal
variables. variables.
Syntax Description |Syntax|Description|
--------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |------|-----------|
`ARRAY[N]=VALUE` Sets the element `N` of the **indexed** array `ARRAY` to `VALUE`. **`N` can be any valid [arithmetic expression](../syntax/arith_expr.md)**. |`ARRAY[N]=VALUE`|Sets the element `N` of the **indexed** array `ARRAY` to `VALUE`. **`N` can be any valid [arithmetic expression](../syntax/arith_expr.md)**.|
`ARRAY[STRING]=VALUE` Sets the element indexed by `STRING` of the **associative array** `ARRAY`. |`ARRAY[STRING]=VALUE`|Sets the element indexed by `STRING` of the **associative array** `ARRAY`.|
`ARRAY=VALUE` As above. If no index is given, as a default the zeroth element is set to `VALUE`. Careful, this is even true of associative arrays - there is no error if no key is specified, and the value is assigned to string index \"0\". |`ARRAY=VALUE`|As above. If no index is given, as a default the zeroth element is set to `VALUE`. Careful, this is even true of associative arrays - there is no error if no key is specified, and the value is assigned to string index "0".|
`ARRAY=(E1\ E2\ ...)` Compound array assignment - sets the whole array `ARRAY` to the given list of elements indexed sequentially starting at zero. The array is unset before assignment unless the += operator is used. When the list is empty (`ARRAY=()`), the array will be set to an empty array. This method obviously does not use explicit indexes. An **associative array** can **not** be set like that! Clearing an associative array using `ARRAY=()` works. |`ARRAY=(E1\ E2\ ...)`|Compound array assignment - sets the whole array `ARRAY` to the given list of elements indexed sequentially starting at zero. The array is unset before assignment unless the += operator is used. When the list is empty (`ARRAY=()`), the array will be set to an empty array. This method obviously does not use explicit indexes. An **associative array** can **not** be set like that! Clearing an associative array using `ARRAY=()` works.|
`ARRAY=([X]=E1\ [Y]=E2\ ...)` Compound assignment for indexed arrays with index-value pairs declared individually (here for example `X` and `Y`). X and Y are arithmetic expressions. This syntax can be combined with the above - elements declared without an explicitly specified index are assigned sequentially starting at either the last element with an explicit index, or zero. |`ARRAY=([X]=E1\ [Y]=E2\ ...)`|Compound assignment for indexed arrays with index-value pairs declared individually (here for example `X` and `Y`). X and Y are arithmetic expressions. This syntax can be combined with the above - elements declared without an explicitly specified index are assigned sequentially starting at either the last element with an explicit index, or zero.|
`ARRAY=([S1]=E1\ [S2]=E2\ ...)` Individual mass-setting for **associative arrays**. The named indexes (here: `S1` and `S2`) are strings. |`ARRAY=([S1]=E1\ [S2]=E2\ ...)`|Individual mass-setting for **associative arrays**. The named indexes (here: `S1` and `S2`) are strings.|
`ARRAY+=(E1\ E2\ ...)` Append to ARRAY. |`ARRAY+=(E1\ E2\ ...)`|Append to ARRAY.|
`ARRAY=("${ANOTHER_ARRAY[@]}")` Copy ANOTHER_ARRAY to ARRAY, copying each element. |`ARRAY=("${ANOTHER_ARRAY[@]}")`|Copy ANOTHER_ARRAY to ARRAY, copying each element.|
As of now, arrays can't be exported. As of now, arrays can't be exported.
### Getting values ### Getting values
<note> For completeness and details on several parameter expansion !!! info ""
variants, see the [article about parameter expansion](../syntax/pe.md) and For completeness and details on several parameter expansion
check the notes about arrays. </note> variants, see the [article about parameter expansion](../syntax/pe.md) and
check the notes about arrays.
Syntax Description |Syntax|Description|
----------------------------------------------------------------------- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |------|-----------|
`${ARRAY[N]}` Expands to the value of the index `N` in the **indexed** array `ARRAY`. If `N` is a negative number, it's treated as the offset from the maximum assigned index (can't be used for assignment) - 1 |`${ARRAY[N]}`|Expands to the value of the index `N` in the **indexed** array `ARRAY`. If `N` is a negative number, it's treated as the offset from the maximum assigned index (can't be used for assignment) - 1|
`${ARRAY[S]}` Expands to the value of the index `S` in the **associative** array `ARRAY`. |`${ARRAY[S]}`|Expands to the value of the index `S` in the **associative** array `ARRAY`.|
`"${ARRAY[@]}" ${ARRAY[@]} "${ARRAY[*]}" ${ARRAY[*]}` Similar to [mass-expanding positional parameters](../scripting/posparams.md#mass_usage), this expands to all elements. If unquoted, both subscripts `*` and `@` expand to the same result, if quoted, `@` expands to all elements individually quoted, `*` expands to all elements quoted as a whole. |`"${ARRAY[@]}" ${ARRAY[@]} "${ARRAY[*]}" ${ARRAY[*]}`|Similar to [mass-expanding positional parameters](../scripting/posparams.md#mass_usage), this expands to all elements. If unquoted, both subscripts `*` and `@` expand to the same result, if quoted, `@` expands to all elements individually quoted, `*` expands to all elements quoted as a whole.|
`"${ARRAY[@]:N:M}" ${ARRAY[@]:N:M} "${ARRAY[*]:N:M}" ${ARRAY[*]:N:M}` Similar to what this syntax does for the characters of a single string when doing [substring expansion](../syntax/pe.md#substring_expansion), this expands to `M` elements starting with element `N`. This way you can mass-expand individual indexes. The rules for quoting and the subscripts `*` and `@` are the same as above for the other mass-expansions. |`"${ARRAY[@]:N:M}" ${ARRAY[@]:N:M} "${ARRAY[*]:N:M}" ${ARRAY[*]:N:M}`|Similar to what this syntax does for the characters of a single string when doing [substring expansion](../syntax/pe.md#substring_expansion), this expands to `M` elements starting with element `N`. This way you can mass-expand individual indexes. The rules for quoting and the subscripts `*` and `@` are the same as above for the other mass-expansions.|
For clarification: When you use the subscripts `@` or `*` for For clarification: When you use the subscripts `@` or `*` for
mass-expanding, then the behaviour is exactly what it is for `$@` and mass-expanding, then the behaviour is exactly what it is for `$@` and
@ -150,62 +151,50 @@ article to understand what's going on.
### Metadata ### Metadata
-------------------------------------------------------------------------------------------------------------------------------- |Syntax|Description|
Syntax Description |------|-----------|
--------------------- ---------------------------------------------------------------------------------------------------------- |`${#ARRAY[N]}`|Expands to the **length** of an individual array member at index `N` (**stringlength**)|
`${#ARRAY[N]}` Expands to the **length** of an individual array member at index `N` (**stringlength**) |`${#ARRAY[STRING]}`|Expands to the **length** of an individual associative array member at index `STRING` (**stringlength**)|
|`${#ARRAY[@]}` \ `${#ARRAY[*]}`|Expands to the **number of elements** in `ARRAY`|
`${#ARRAY[STRING]}` Expands to the **length** of an individual associative array member at index `STRING` (**stringlength**) |`${!ARRAY[@]}` \ `${!ARRAY[*]}`|Expands to the **indexes** in `ARRAY` since BASH 3.0|
`${#ARRAY[@]}`\ Expands to the **number of elements** in `ARRAY`
`${#ARRAY[*]}`
`${!ARRAY[@]}`\ Expands to the **indexes** in `ARRAY` since BASH 3.0
`${!ARRAY[*]}`
--------------------------------------------------------------------------------------------------------------------------------
### Destruction ### Destruction
The [unset](../commands/builtin/unset.md) builtin command is used to destroy The [unset](../commands/builtin/unset.md) builtin command is used to destroy
(unset) arrays or individual elements of arrays. (unset) arrays or individual elements of arrays.
-------------------------------------------------------------------------------------------------- |Syntax|Description|
Syntax Description |------|-----------|
-------------------------- ----------------------------------------------------------------------- |`unset -v ARRAY` \ `unset -v ARRAY[@]` \ `unset -v ARRAY[*]`|Destroys a complete array|
`unset -v ARRAY`\ Destroys a complete array |`unset -v ARRAY[N]`|Destroys the array element at index `N`|
`unset -v ARRAY[@]`\ |`unset -v ARRAY[STRING]`|Destroys the array element of the associative array at index `STRING`|
`unset -v ARRAY[*]`
`unset -v ARRAY[N]` Destroys the array element at index `N`
`unset -v ARRAY[STRING]` Destroys the array element of the associative array at index `STRING`
--------------------------------------------------------------------------------------------------
It is best to [explicitly specify It is best to [explicitly specify
-v](../commands/builtin/unset.md#portability_considerations) when unsetting -v](../commands/builtin/unset.md#portability_considerations) when unsetting
variables with unset. variables with unset.
<note warning> Specifying unquoted array elements as arguments to any !!! warning "warning"
command, such as with the syntax above **may cause [pathname Specifying unquoted array elements as arguments to any
expansion](../syntax/expansion/globs.md) to occur** due to the presence of command, such as with the syntax above **may cause [pathname
glob characters. expansion](../syntax/expansion/globs.md) to occur** due to the presence of
glob characters.
Example: You are in a directory with a file named `x1`, and you want to Example: You are in a directory with a file named `x1`, and you want to
destroy an array element `x[1]`, with destroy an array element `x[1]`, with
unset x[1] unset x[1]
then pathname expansion will expand to the filename `x1` and break your then pathname expansion will expand to the filename `x1` and break your
processing! processing!
Even worse, if `nullglob` is set, your array/index will disappear. Even worse, if `nullglob` is set, your array/index will disappear.
To avoid this, **always quote** the array name and index: To avoid this, **always quote** the array name and index:
unset -v 'x[1]' unset -v 'x[1]'
This applies generally to all commands which take variable names as This applies generally to all commands which take variable names as
arguments. Single quotes preferred. </note> arguments. Single quotes preferred.
## Usage ## Usage
@ -247,7 +236,7 @@ The method above, walking through an array by just knowing its number of
elements, only works for arrays where all elements are set, of course. elements, only works for arrays where all elements are set, of course.
If one element in the middle is removed, then the calculation is If one element in the middle is removed, then the calculation is
nonsense, because the number of elements doesn't correspond to the nonsense, because the number of elements doesn't correspond to the
highest used index anymore (we call them \"*sparse arrays*\"). highest used index anymore (we call them "*sparse arrays*").
Now, suppose that you want to replace your array `sentence` with the Now, suppose that you want to replace your array `sentence` with the
values in the [previously-declared array](#purpose) `NAMES` . You might values in the [previously-declared array](#purpose) `NAMES` . You might
@ -297,7 +286,7 @@ starting at zero) just is replaced with an arbitrary string:
sentence[End]='in what you send' sentence[End]='in what you send'
sentence['Very end']=... sentence['Very end']=...
[**Beware:**]{.underline} don't rely on the fact that the elements are <u>**Beware:**</u> don't rely on the fact that the elements are
ordered in memory like they were declared, it could look like this: ordered in memory like they were declared, it could look like this:
# output from 'set' command # output from 'set' command
@ -320,9 +309,9 @@ associative array indexed with the SHA sum of the files:
# Thanks to Tramp in #bash for the idea and the code # Thanks to Tramp in #bash for the idea and the code
unset flist; declare -A flist; unset flist; declare -A flist;
while read -r sum fname; do while read -r sum fname; do
if [[ ${flist[$sum]} ]]; then if [[ ${flist[$sum]} ]]; then
printf 'rm -- "%s" # Same as >%s<\n' "$fname" "${flist[$sum]}" printf 'rm -- "%s" # Same as >%s<\n' "$fname" "${flist[$sum]}"
else else
flist[$sum]="$fname" flist[$sum]="$fname"
fi fi
@ -369,13 +358,13 @@ strings would have been inserted into the integer array without
evaluating the arithmetic. A special-case of this is shown in the next evaluating the arithmetic. A special-case of this is shown in the next
section. section.
<note> Bash declaration commands are really keywords in disguise. They !!! info "info"
magically parse arguments to determine whether they are in the form of a Bash declaration commands are really keywords in disguise. They
valid assignment. If so, they are evaluated as assignments. If not, they magically parse arguments to determine whether they are in the form of a
are undergo normal argument expansion before being passed to the builtin valid assignment. If so, they are evaluated as assignments. If not, they
which evaluates the resulting string as an assignment (somewhat like are undergo normal argument expansion before being passed to the builtin
`eval`, but there are differences.) `'Todo:`\' Discuss this in detail. which evaluates the resulting string as an assignment (somewhat like
</note> `eval`, but there are differences.) `'Todo:`\' Discuss this in detail.
### Indirection ### Indirection
@ -385,7 +374,7 @@ syntax. Parameters whose values are of the form: `name[index]`,
results. This is mainly useful for passing arrays (especially multiple results. This is mainly useful for passing arrays (especially multiple
arrays) by name to a function. arrays) by name to a function.
This example is an \"isSubset\"-like predicate which returns true if all This example is an "isSubset"-like predicate which returns true if all
key-value pairs of the array given as the first argument to isSubset key-value pairs of the array given as the first argument to isSubset
correspond to a key-value of the array given as the second argument. It correspond to a key-value of the array given as the second argument. It
demonstrates both indirect array expansion and indirect key-passing demonstrates both indirect array expansion and indirect key-passing
@ -550,7 +539,7 @@ dynamically calls a function whose name is resolved from the array.
the subscript or the value first can change in almost every shell the subscript or the value first can change in almost every shell
for both expansions and arithmetic variables. See [evaluation for both expansions and arithmetic variables. See [evaluation
order](#evaluation_order) for details. order](#evaluation_order) for details.
- Bash 4.1.\* and below cannot use negative subscripts to address - Bash 4.1.* and below cannot use negative subscripts to address
array indexes relative to the highest-numbered index. You must use array indexes relative to the highest-numbered index. You must use
the subscript expansion, i.e. `"${arr[@]:(-n):1}"`, to expand the the subscript expansion, i.e. `"${arr[@]:(-n):1}"`, to expand the
nth-last element (or the next-highest indexed after `n` if `arr[n]` nth-last element (or the next-highest indexed after `n` if `arr[n]`
@ -570,7 +559,7 @@ dynamically calls a function whose name is resolved from the array.
### Bugs ### Bugs
- **Fixed in 4.3** Bash 4.2.\* and earlier considers each chunk of a - **Fixed in 4.3** Bash 4.2.* and earlier considers each chunk of a
compound assignment, including the subscript for globbing. The compound assignment, including the subscript for globbing. The
subscript part is considered quoted, but any unquoted glob subscript part is considered quoted, but any unquoted glob
characters on the right-hand side of the `[...]=` will be clumped characters on the right-hand side of the `[...]=` will be clumped
@ -586,7 +575,7 @@ dynamically calls a function whose name is resolved from the array.
1=a 1=a
` `
- **Fixed in 4.3** In addition to the above globbing issue, - **Fixed in 4.3** In addition to the above globbing issue,
assignments preceding \"declare\" have an additional effect on brace assignments preceding "declare" have an additional effect on brace
and pathname expansion. `$ set -x; foo=bar declare arr=( {1..10} ) and pathname expansion. `$ set -x; foo=bar declare arr=( {1..10} )
+ foo=bar + foo=bar
+ declare 'arr=(1)' 'arr=(2)' 'arr=(3)' 'arr=(4)' 'arr=(5)' 'arr=(6)' 'arr=(7)' 'arr=(8)' 'arr=(9)' 'arr=(10)' + declare 'arr=(1)' 'arr=(2)' 'arr=(3)' 'arr=(4)' 'arr=(5)' 'arr=(6)' 'arr=(7)' 'arr=(8)' 'arr=(9)' 'arr=(10)'
@ -687,6 +676,3 @@ to generate these results.
detailed discussion on arrays with many examples. detailed discussion on arrays with many examples.
- [BashSheet - Arrays](http://mywiki.wooledge.org/BashSheet#Arrays) - - [BashSheet - Arrays](http://mywiki.wooledge.org/BashSheet#Arrays) -
Bashsheet quick-reference on Greycat's wiki. Bashsheet quick-reference on Greycat's wiki.
<div hide> vim: set fenc=utf-8 ff=unix ts=4 sts=4 sw=4 ft=dokuwiki et
wrap lbr: </div>

View File

@ -12,7 +12,7 @@ tags:
Bash builds its features on top of a few basic **grammar rules**. The Bash builds its features on top of a few basic **grammar rules**. The
code you see everywhere, the code you use, is based on those rules. code you see everywhere, the code you use, is based on those rules.
However, **this is a very theoretical view**, but if you\'re interested, However, **this is a very theoretical view**, but if you're interested,
it may help you understand why things look the way they look. it may help you understand why things look the way they look.
If you don't know the commands used in the following examples, just If you don't know the commands used in the following examples, just
@ -36,7 +36,7 @@ Every complex Bash operation can be split into simple commands:
ls -l ls -l
LC_ALL=C ls LC_ALL=C ls
The last one might not be familiar. That one simply adds \"`LC_ALL=C`\" The last one might not be familiar. That one simply adds "`LC_ALL=C`"
to the environment of the `ls` program. It doesn't affect your current to the environment of the `ls` program. It doesn't affect your current
shell. This also works while calling functions, unless Bash runs in shell. This also works while calling functions, unless Bash runs in
POSIX(r) mode (in which case it affects your current shell). POSIX(r) mode (in which case it affects your current shell).
@ -46,19 +46,21 @@ can catch it and act on it. Exit code range is from 0 to 255, where 0
means success, and the rest mean either something failed, or there is an means success, and the rest mean either something failed, or there is an
issue to report back to the calling program. issue to report back to the calling program.
<wrap center round info 90%> The simple command construct is the !!! info "info"
**base** for all higher constructs. Everything you execute, from The simple command construct is the
pipelines to functions, finally ends up in (many) simple commands. **base** for all higher constructs. Everything you execute, from
That's why Bash only has one method to [expand and execute a simple pipelines to functions, finally ends up in (many) simple commands.
command](../syntax/grammar/parser_exec.md). </wrap> That's why Bash only has one method to [expand and execute a simple
command](../syntax/grammar/parser_exec.md).
## Pipelines ## Pipelines
FIXME Missing an additional article about pipelines and pipelining !!! warning "FIXME"
Missing an additional article about pipelines and pipelining
`[time [-p]] [ ! ] command [ | command2 ... ]` `[time [-p]] [ ! ] command [ | command2 ... ]`
**Don't get confused** about the name \"pipeline.\" It's a grammatic **Don't get confused** about the name "pipeline." It's a grammatic
name for a construct. Such a pipeline isn't necessarily a pair of name for a construct. Such a pipeline isn't necessarily a pair of
commands where stdout/stdin is connected via a real pipe. commands where stdout/stdin is connected via a real pipe.
@ -73,10 +75,10 @@ count the lines generated by the ls command. The result is the number of
directory entries in /etc. directory entries in /etc.
The last command in the pipeline will set the exit code for the The last command in the pipeline will set the exit code for the
pipeline. This exit code can be \"inverted\" by prefixing an exclamation pipeline. This exit code can be "inverted" by prefixing an exclamation
mark to the pipeline: An unsuccessful pipeline will exit \"successful\" mark to the pipeline: An unsuccessful pipeline will exit "successful"
and vice versa. In this example, the commands in the if stanza will be and vice versa. In this example, the commands in the if stanza will be
executed if the pattern \"\^root:\" is **not** found in `/etc/passwd`: executed if the pattern "^root:" is **not** found in `/etc/passwd`:
if ! grep '^root:' /etc/passwd; then if ! grep '^root:' /etc/passwd; then
echo "No root user defined... eh?" echo "No root user defined... eh?"
@ -85,10 +87,10 @@ executed if the pattern \"\^root:\" is **not** found in `/etc/passwd`:
Yes, this is also a pipeline (although there is no pipe!), because the Yes, this is also a pipeline (although there is no pipe!), because the
**exclamation mark to invert the exit code** can only be used in a **exclamation mark to invert the exit code** can only be used in a
pipeline. If `grep`'s exit code is 1 (FALSE) (the text was not found), pipeline. If `grep`'s exit code is 1 (FALSE) (the text was not found),
the leading `!` will \"invert\" the exit code, and the shell sees (and the leading `!` will "invert" the exit code, and the shell sees (and
acts on) exit code 0 (TRUE) and the `then` part of the `if` stanza is acts on) exit code 0 (TRUE) and the `then` part of the `if` stanza is
executed. One could say we checked for executed. One could say we checked for
\"`not grep "^root" /etc/passwd`\". "`not grep "^root" /etc/passwd`".
The [set option pipefail](../commands/builtin/set.md#attributes) determines The [set option pipefail](../commands/builtin/set.md#attributes) determines
the behavior of how bash reports the exit code of a pipeline. If it's the behavior of how bash reports the exit code of a pipeline. If it's
@ -117,7 +119,8 @@ syntax:
## Lists ## Lists
FIXME Missing an additional article about list operators !!! warning "FIXME"
Missing an additional article about list operators
A list is a sequence of one or more [pipelines](#pipelines) A list is a sequence of one or more [pipelines](#pipelines)
separated by one of the operators `;`, `&`, `&&`, or `││`, and separated by one of the operators `;`, `&`, `&&`, or `││`, and
@ -128,15 +131,15 @@ that all have **different meanings** for Bash.
Your whole Bash script technically is one big single list! Your whole Bash script technically is one big single list!
Operator Description |Operator|Description|
------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |--------|-----------|
`<PIPELINE1> <newline> <PIPELINE2>` Newlines completely separate pipelines. The next pipeline is executed without any checks. (You enter a command and press `<RETURN>`!) |`<PIPELINE1> <newline> <PIPELINE2>`|Newlines completely separate pipelines. The next pipeline is executed without any checks. (You enter a command and press `<RETURN>`!)|
`<PIPELINE1> ; <PIPELINE2>` The semicolon does what `<newline>` does: It separates the pipelines |`<PIPELINE1> ; <PIPELINE2>`|The semicolon does what `<newline>` does: It separates the pipelines|
`<PIPELINE> & <PIPELINE>` The pipeline in front of the `&` is executed **asynchronously** (\"in the background\"). If a pipeline follows this, it is executed immediately after the async pipeline starts |`<PIPELINE> & <PIPELINE>`|The pipeline in front of the `&` is executed **asynchronously** ("in the background"). If a pipeline follows this, it is executed immediately after the async pipeline starts|
`<PIPELINE1> && <PIPELINE2>` `<PIPELINE1>` is executed and **only** if its exit code was 0 (TRUE), then `<PIPELINE2>` is executed (AND-List) |`<PIPELINE1> && <PIPELINE2>`|`<PIPELINE1>` is executed and **only** if its exit code was 0 (TRUE), then `<PIPELINE2>` is executed (AND-List)|
`<PIPELINE1> || <PIPELINE2>` `<PIPELINE1>` is executed and **only** if its exit code was **not** 0 (FALSE), then `<PIPELINE2>` is executed (OR-List) |`<PIPELINE1>||<PIPELINE2>`|`<PIPELINE1>` is executed and **only** if its exit code was **not** 0 (FALSE), then `<PIPELINE2>` is executed (OR-List)|
**Note:** POSIX calls this construct a \"compound lists\". **Note:** POSIX calls this construct a "compound lists".
## Compound Commands ## Compound Commands
@ -144,7 +147,7 @@ See also the [list of compound commands](../syntax/ccmd/intro.md).
There are two forms of compound commands: There are two forms of compound commands:
- form a new syntax element using a list as a \"body\" - form a new syntax element using a list as a "body"
- completly independant syntax elements - completly independant syntax elements
Essentially, everything else that's not described in this article. Essentially, everything else that's not described in this article.
@ -157,29 +160,30 @@ Compound commands have the following characteristics:
See the following table for a short overview (no details - just an See the following table for a short overview (no details - just an
overview): overview):
Compound command syntax Description |Compound command syntax|Description|
------------------------------------------------------------ --------------------------------------------------------------------------------------------------------------------------------------------------------- |-----------------------|-----------|
`( <LIST> )` Execute `<LIST>` in an extra subshell => [article](../syntax/ccmd/grouping_subshell.md) |`( <LIST> )`|Execute `<LIST>` in an extra subshell =\> [article](../syntax/ccmd/grouping_subshell.md)|
`{ <LIST> ; }` Execute `<LIST>` as separate group (but not in a subshell) => [article](../syntax/ccmd/grouping_plain.md) |`{ <LIST> ; }`|Execute `<LIST>` as separate group (but not in a subshell) =\> [article](../syntax/ccmd/grouping_plain.md)|
`(( <EXPRESSION> ))` Evaluate the arithmetic expression `<EXPRESSION>` => [article](../syntax/ccmd/arithmetic_eval.md) |`(( <EXPRESSION> ))`|Evaluate the arithmetic expression `<EXPRESSION>` =\> [article](../syntax/ccmd/arithmetic_eval.md)|
`[[ <EXPRESSION> ]]` Evaluate the conditional expression `<EXPRESSION>` (aka \"the new test command\") => [article](../syntax/ccmd/conditional_expression.md) |`[[ <EXPRESSION> ]]`|Evaluate the conditional expression `<EXPRESSION>` (aka "the new test command") =\> [article](../syntax/ccmd/conditional_expression.md)|
`for <NAME> in <WORDS> ; do <LIST> ; done` Executes `<LIST>` while setting the variable `<NAME>` to one of `<WORDS>` on every iteration (classic for-loop) => [article](../syntax/ccmd/classic_for.md) |`for <NAME> in <WORDS> ; do <LIST> ; done`|Executes `<LIST>` while setting the variable `<NAME>` to one of `<WORDS>` on every iteration (classic for-loop) =\> [article](../syntax/ccmd/classic_for.md)|
`for (( <EXPR1> ; <EXPR2> ; <EXPR3> )) ; do <LIST> ; done` C-style for-loop (driven by arithmetic expressions) => [article](../syntax/ccmd/c_for.md) |`for (( <EXPR1> ; <EXPR2> ; <EXPR3> )) ; do <LIST> ; done`|C-style for-loop (driven by arithmetic expressions) =\> [article](../syntax/ccmd/c_for.md)|
`select <NAME> in <WORDS> ; do <LIST> ; done` Provides simple menus => [article](../syntax/ccmd/user_select.md) |`select <NAME> in <WORDS> ; do <LIST> ; done`|Provides simple menus =\> [article](../syntax/ccmd/user_select.md)|
`case <WORD> in <PATTERN>) <LIST> ;; ... esac` Decisions based on pattern matching - executing `<LIST>` on match => [article](../syntax/ccmd/case.md) |`case <WORD> in <PATTERN>) <LIST> ;; ... esac`|Decisions based on pattern matching - executing `<LIST>` on match =\> [article](../syntax/ccmd/case.md)|
`if <LIST> ; then <LIST> ; else <LIST> ; fi` The if clause: makes decisions based on exit codes => [article](../syntax/ccmd/if_clause.md) |`if <LIST> ; then <LIST> ; else <LIST> ; fi`|The if clause: makes decisions based on exit codes =\> [article](../syntax/ccmd/if_clause.md)|
`while <LIST1> ; do <LIST2> ; done` Execute `<LIST2>` while `<LIST1>` returns TRUE (exit code) => [article](../syntax/ccmd/while_loop.md) |`while <LIST1> ; do <LIST2> ; done`|Execute `<LIST2>` while `<LIST1>` returns TRUE (exit code) =\> [article](../syntax/ccmd/while_loop.md)|
`until <LIST1> ; do <LIST2> ; done` Execute `<LIST2>` until `<LIST1>` returns TRUE (exit code) => [article](../syntax/ccmd/until_loop.md) |`until <LIST1> ; do <LIST2> ; done`|Execute `<LIST2>` until `<LIST1>` returns TRUE (exit code) =\> [article](../syntax/ccmd/until_loop.md)|
## Shell Function Definitions ## Shell Function Definitions
FIXME Missing an additional article about shell functions !!! warning "FIXME"
Missing an additional article about shell functions
A shell function definition makes a [compound A shell function definition makes a [compound
command](#compound_commands) available via a new name. When command](#compound_commands) available via a new name. When
the function runs, it has its own \"private\" set of positional the function runs, it has its own "private" set of positional
parameters and I/O descriptors. It acts like a script-within-the-script. parameters and I/O descriptors. It acts like a script-within-the-script.
Simply stated: **You\'ve created a new command.** Simply stated: **You've created a new command.**
The definition is easy (one of many possibilities): The definition is easy (one of many possibilities):
@ -219,7 +223,7 @@ without the space.
I suggest using the first form. It's specified in POSIX and all I suggest using the first form. It's specified in POSIX and all
Bourne-like shells seem to support it. Bourne-like shells seem to support it.
[**Note:**]{.underline} Before version `2.05-alpha1`, Bash only <u>**Note:**</u> Before version `2.05-alpha1`, Bash only
recognized the definition using curly braces (`name() { ... }`), other recognized the definition using curly braces (`name() { ... }`), other
shells allow the definition using **any** command (not just the compound shells allow the definition using **any** command (not just the compound
command set). command set).
@ -237,16 +241,16 @@ like this:
} }
# this $1 belongs the script itself! # this $1 belongs the script itself!
mycmd "$1" # Execute command immediately after defining function mycmd "$1" # Execute command immediately after defining function
exit 0 exit 0
**Just informational(1):** **Just informational(1):**
Internally, for forking, Bash stores function definitions in environment Internally, for forking, Bash stores function definitions in environment
variables. Variables with the content \"*() \....*\". variables. Variables with the content "*() ....*".
Something similar to the following works without \"officially\" Something similar to the following works without "officially"
declaring a function: declaring a function:
$ export testfn="() { echo test; }" $ export testfn="() { echo test; }"
@ -267,8 +271,8 @@ The elements of this name aren't subject to a path search.
Weird function names should not be used. Quote from the maintainer: Weird function names should not be used. Quote from the maintainer:
- * It was a mistake to allow such characters in function names - * It was a mistake to allow such characters in function names
(\`unset\' doesn't work to unset them without forcing -f, for (`unset` doesn't work to unset them without forcing `-f`, for
instance). We\'re stuck with them for backwards compatibility, but I instance). We're stuck with them for backwards compatibility, but I
don't have to encourage their use. * don't have to encourage their use. *
## Grammar summary ## Grammar summary
@ -288,15 +292,16 @@ Weird function names should not be used. Quote from the maintainer:
## Examples for classification ## Examples for classification
FIXME more\... !!! warning "FIXME"
more...
------------------------------------------------------------------------ ------------------------------------------------------------------------
[A (very) simple command]{.underline} <u>A (very) simple command</u>
echo "Hello world..." echo "Hello world..."
[All of the following are simple commands]{.underline} <u>All of the following are simple commands</u>
x=5 x=5
@ -306,7 +311,7 @@ FIXME more\...
------------------------------------------------------------------------ ------------------------------------------------------------------------
[A common compound command]{.underline} <u>A common compound command</u>
if [ -d /data/mp3 ]; then if [ -d /data/mp3 ]; then
cp mymusic.mp3 /data/mp3 cp mymusic.mp3 /data/mp3

View File

@ -20,10 +20,10 @@
The C-style for-loop is a [compound The C-style for-loop is a [compound
command](../../syntax/basicgrammar.md#compound_commands) derived from the command](../../syntax/basicgrammar.md#compound_commands) derived from the
equivalent ksh88 feature, which is in turn derived from the C \"for\" equivalent ksh88 feature, which is in turn derived from the C "for"
keyword. Its purpose is to provide a convenient way to evaluate keyword. Its purpose is to provide a convenient way to evaluate
arithmetic expressions in a loop, plus initialize any required arithmetic expressions in a loop, plus initialize any required
arithmetic variables. It is one of the main \"loop with a counter\" arithmetic variables. It is one of the main "loop with a counter"
mechanisms available in the language. mechanisms available in the language.
The `((;;))` syntax at the top of the loop is not an ordinary The `((;;))` syntax at the top of the loop is not an ordinary
@ -103,7 +103,7 @@ functions and local variables for initialization.</div>
### Simple counter ### Simple counter
A simple counter, the loop iterates 101 times (\"0\" to \"100\" are 101 A simple counter, the loop iterates 101 times ("0" to "100" are 101
numbers -> 101 runs!), and everytime the variable `x` is set to the numbers -> 101 runs!), and everytime the variable `x` is set to the
current value. current value.
@ -111,9 +111,6 @@ current value.
- Before every iteration it **checks** if `x ≤ 100` - Before every iteration it **checks** if `x ≤ 100`
- After every iteration it **changes** `x++` - After every iteration it **changes** `x++`
```{=html}
<!-- -->
```
for ((x = 0 ; x <= 100 ; x++)); do for ((x = 0 ; x <= 100 ; x++)); do
echo "Counter: $x" echo "Counter: $x"
done done
@ -131,8 +128,8 @@ will count from 0 to 100, but with a **step of 10**.
### Bits analyzer ### Bits analyzer
This example loops through the bit-values of a Byte, beginning from 128, This example loops through the bit-values of a Byte, beginning from 128,
ending at 1. If that bit is set in the `testbyte`, it prints \"`1`\", ending at 1. If that bit is set in the `testbyte`, it prints "`1`",
else \"`0`\" => it prints the binary representation of the `testbyte` else "`0`" => it prints the binary representation of the `testbyte`
value (8 bits). value (8 bits).
#!/usr/bin/env bash #!/usr/bin/env bash
@ -161,7 +158,7 @@ value (8 bits).
# vim: set fenc=utf-8 ff=unix ft=sh : # vim: set fenc=utf-8 ff=unix ft=sh :
<div hide> <div hide>
testbyte=123 testbyte=123
for (( n = 128 ; n >= 1 ; n /= 2 )); do for (( n = 128 ; n >= 1 ; n /= 2 )); do
@ -173,11 +170,11 @@ value (8 bits).
done done
echo echo
</div> </div>
Why that one begins at 128 (highest value, on the left) and not 1 Why that one begins at 128 (highest value, on the left) and not 1
(lowest value, on the right)? It's easier to print from left to (lowest value, on the right)? It's easier to print from left to
right\... right...
We arrive at 128 for `n` through the recursive arithmetic expression We arrive at 128 for `n` through the recursive arithmetic expression
stored in `x`, which calculates the next-greatest power of 2 after `m`. stored in `x`, which calculates the next-greatest power of 2 after `m`.
@ -186,7 +183,7 @@ it has a built-in feature for `printf` to print a representation of any
number in an arbitrary base (up to 64). Very few languages have that number in an arbitrary base (up to 64). Very few languages have that
ability built-in, even things like Python. ability built-in, even things like Python.
### Up, down, up, down\... ### Up, down, up, down...
This counts up and down from `0` to `${1:-5}`, `${2:-4}` times, This counts up and down from `0` to `${1:-5}`, `${2:-4}` times,
demonstrating more complicated arithmetic expressions with multiple demonstrating more complicated arithmetic expressions with multiple
@ -196,7 +193,8 @@ variables.
printf '%*s\n' "$((n+1))" "$n" printf '%*s\n' "$((n+1))" "$n"
done done
<code> \~ \$ bash <(xclip -o) 1 ``` bash
~ \$ bash <(xclip -o) 1
2 2
3 3
@ -216,7 +214,8 @@ variables.
3 3
2 2
1 </code> 1
```
## Portability considerations ## Portability considerations

View File

@ -43,7 +43,7 @@ done**, which means you can leave expansions unquoted without problems:
esac esac
This is similar to the behavior of the [conditional expression command This is similar to the behavior of the [conditional expression command
(\"new test command\")](../../syntax/ccmd/conditional_expression.md) (also no ("new test command")](../../syntax/ccmd/conditional_expression.md) (also no
word splitting for expansions). word splitting for expansions).
Unlike the C-case-statement, only the matching list and nothing else is Unlike the C-case-statement, only the matching list and nothing else is
@ -55,13 +55,13 @@ This is a POSIX-compatable equivalent to the `@(pattern-list)` extglob
construct. construct.
The `case` statement is one of the most difficult commands to indent The `case` statement is one of the most difficult commands to indent
clearly, and people frequently ask about the most \"correct\" style. clearly, and people frequently ask about the most "correct" style.
Just do your best - there are many variations of indenting style for Just do your best - there are many variations of indenting style for
`case` and no real agreed-upon best practice. `case` and no real agreed-upon best practice.
## Examples ## Examples
Another one of my stupid examples\... Another one of my stupid examples...
printf '%s ' 'Which fruit do you like most?' printf '%s ' 'Which fruit do you like most?'
read -${BASH_VERSION+e}r fruit read -${BASH_VERSION+e}r fruit

View File

@ -23,7 +23,7 @@ alternative, historical and undocumented syntax [^1]
## Description ## Description
For every word in `<WORDS>`, one iteration of the loop is performed and For every word in `<WORDS>`, one iteration of the loop is performed and
the variable `<NAME>` is set to the current word. If no \"`in <WORDS>`\" the variable `<NAME>` is set to the current word. If no "`in <WORDS>`"
is present to give an own word-list, then the positional parameters is present to give an own word-list, then the positional parameters
(`"$@"`) are used (the arguments to the script or function). In this (`"$@"`) are used (the arguments to the script or function). In this
case (and only in this case), the semicolon between the variable name case (and only in this case), the semicolon between the variable name
@ -60,14 +60,14 @@ specified by POSIX(r).
The return status is the one of the last command executed in `<LIST>` or The return status is the one of the last command executed in `<LIST>` or
`0` (`TRUE`), if the item list `<WORDS>` evaluates to nothing (i.e.: `0` (`TRUE`), if the item list `<WORDS>` evaluates to nothing (i.e.:
\"is empty\"!). "is empty"!).
## Examples ## Examples
### Iterate over array elements ### Iterate over array elements
With some array syntax (see [arrays](../../syntax/arrays.md)) you can easily With some array syntax (see [arrays](../../syntax/arrays.md)) you can easily
\"feed\" the for-loop to iterate over all elements in an array (by "feed" the for-loop to iterate over all elements in an array (by
mass-expanding all elements): mass-expanding all elements):
``` bash ``` bash
@ -156,7 +156,7 @@ done
### Loop over a number range ### Loop over a number range
Beginning in Bash 4, you can also use \"sequence expression\" form of Beginning in Bash 4, you can also use "sequence expression" form of
[brace expansion](../../syntax/expansion/brace.md) syntax when looping over [brace expansion](../../syntax/expansion/brace.md) syntax when looping over
numbers, and this form does not create leading zeroes unless you ask for numbers, and this form does not create leading zeroes unless you ask for
them: them:

View File

@ -16,28 +16,17 @@ The testing features basically are the same (see the lists for [classic
test command](../../commands/classictest.md)), with some additions and test command](../../commands/classictest.md)), with some additions and
extensions. extensions.
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |Operator|Description|
Operator Description |--|--|
-------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------- |`( <EXPRESSION> )`|Used to group expressions, to influence precedence of operators|
`( <EXPRESSION> )` Used to group expressions, to influence precedence of operators |`<EXPRESSION1> && <EXPRESSION2>`|`TRUE` if `<EXPRESSION1>`**and**`<EXPRESSION2>` are `TRUE` (do **not** use `-a`!)|
|`<EXPRESSION1>||<EXPRESSION2>`|`TRUE` if `<EXPRESSION1>`**or**`<EXPRESSION2>` is `TRUE` (do **not** use `-o`!)|
`<EXPRESSION1> && <EXPRESSION2>` `TRUE` if `<EXPRESSION1>`**and**`<EXPRESSION2>` are `TRUE` (do **not** use `-a`!) |`<STRING> == <PATTERN>`|`<STRING>` is checked against the pattern `<PATTERN>` - `TRUE` on a match<br>*But note¹, quoting the pattern forces a literal comparison.*|
|`<STRING> = <PATTERN>`|equivalent to the `==` operator|
`<EXPRESSION1> || <EXPRESSION2>` `TRUE` if `<EXPRESSION1>`**or**`<EXPRESSION2>` is `TRUE` (do **not** use `-o`!) |`<STRING> != <PATTERN>`|`<STRING>` is checked against the pattern `<PATTERN>` - `TRUE` on **no match**|
|`<STRING> =~ <ERE>`|`<STRING>` is checked against the [extended regular expression](https://en.wikipedia.org/wiki/Regular_expression#POSIX_extended) `<ERE>` - `TRUE` on a match|
`<STRING> == <PATTERN>` `<STRING>` is checked against the pattern `<PATTERN>` - `TRUE` on a match\ |See the [classic test operators](../../commands/classictest.md#file_tests)|Do **not** use the `test`-typical operators `-a` and `-o` for AND and OR.|
*But note¹, quoting the pattern forces a literal comparison.* |See also [arithmetic comparisons](../../syntax/arith_expr.md#comparisons)|Using `(( <EXPRESSION> ))`, the [arithmetic expression compound command](../../syntax/ccmd/arithmetic_eval.md)|
`<STRING> = <PATTERN>` equivalent to the `==` operator
`<STRING> != <PATTERN>` `<STRING>` is checked against the pattern `<PATTERN>` - `TRUE` on **no match**
`<STRING> =~ <ERE>` `<STRING>` is checked against the [extended regular expression](https://en.wikipedia.org/wiki/Regular_expression#POSIX_extended) `<ERE>` - `TRUE` on a match
See the [classic test operators](../../commands/classictest.md#file_tests) Do **not** use the `test`-typical operators `-a` and `-o` for AND and OR.
See also [arithmetic comparisons](../../syntax/arith_expr.md#comparisons) Using `(( <EXPRESSION> ))`, the [arithmetic expression compound command](../../syntax/ccmd/arithmetic_eval.md)
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
When the `==` and `!=` operators are used, the string to the right of When the `==` and `!=` operators are used, the string to the right of
the operator is considered a pattern and matched according to the rules the operator is considered a pattern and matched according to the rules
@ -50,7 +39,7 @@ literal string.
When the operators `<` and `>` are used (string collation order), the When the operators `<` and `>` are used (string collation order), the
test happens using the current locale when the `compat` level is greater test happens using the current locale when the `compat` level is greater
than \"40\". than "40".
Operator precedence (highest => lowest): Operator precedence (highest => lowest):
@ -151,7 +140,7 @@ Example:
### Behaviour differences compared to the builtin test command ### Behaviour differences compared to the builtin test command
As of Bash 4.1 alpha, the test primaries \'<\' and \'>\' (compare As of Bash 4.1 alpha, the test primaries '&lt;' and '&gt;' (compare
strings lexicographically) use the current locale settings, while the strings lexicographically) use the current locale settings, while the
same primitives for the builtin test command don't. This leads to the same primitives for the builtin test command don't. This leads to the
following situation where they behave differently: following situation where they behave differently:
@ -180,7 +169,7 @@ both contains whitespace and is not the result of an expansion.
- `[[ ... ]]` functionality isn't specified by POSIX(R), though it's - `[[ ... ]]` functionality isn't specified by POSIX(R), though it's
a reserved word a reserved word
- Amongst the major \"POSIX-shell superset languages\" (for lack of a - Amongst the major "POSIX-shell superset languages" (for lack of a
better term) which do have `[[`, the test expression compound better term) which do have `[[`, the test expression compound
command is one of the very most portable non-POSIX features. Aside command is one of the very most portable non-POSIX features. Aside
from the `=~` operator, almost every major feature is consistent from the `=~` operator, almost every major feature is consistent

View File

@ -13,7 +13,7 @@
The [list](../../syntax/basicgrammar.md#lists) `<LIST>` is simply executed in The [list](../../syntax/basicgrammar.md#lists) `<LIST>` is simply executed in
the **current** shell environment. The list must be terminated with a the **current** shell environment. The list must be terminated with a
**newline** or **semicolon**. For parsing reasons, the curly braces must **newline** or **semicolon**. For parsing reasons, the curly braces must
be separated from `<LIST>` by a **semicolon** and **blanks** if they\'re be separated from `<LIST>` by a **semicolon** and **blanks** if they're
in the same line! [^1][^2] in the same line! [^1][^2]
This is known as a **group command**. The return status is the [exit This is known as a **group command**. The return status is the [exit

View File

@ -8,7 +8,7 @@
The [list](../../syntax/basicgrammar.md#lists) `<LIST>` is executed in a The [list](../../syntax/basicgrammar.md#lists) `<LIST>` is executed in a
separate shell - a subprocess. No changes to the environment (variables separate shell - a subprocess. No changes to the environment (variables
etc\...) are reflected in the \"main shell\". etc...) are reflected in the "main shell".
## Examples ## Examples

View File

@ -1,10 +1,10 @@
# Bash compound commands # Bash compound commands
The main part of Bash's syntax are the so-called **compound commands**. The main part of Bash's syntax are the so-called **compound commands**.
They\'re called like that because they use \"real\" commands ([simple They're called like that because they use "real" commands ([simple
commands](../../syntax/basicgrammar.md#simple_commands) or commands](../../syntax/basicgrammar.md#simple_commands) or
[lists](../../syntax/basicgrammar.md#lists)) and knit some intelligence around [lists](../../syntax/basicgrammar.md#lists)) and knit some intelligence around
them. That is what the essential \"Bash language\" is made of. them. That is what the essential "Bash language" is made of.
## Command grouping ## Command grouping
@ -17,7 +17,7 @@ Note that conditionals can also be scripted using
[list](../../syntax/basicgrammar.md#lists), which are syntax elements, not [list](../../syntax/basicgrammar.md#lists), which are syntax elements, not
commands. commands.
- the \"new\" test command: [conditional - the "new" test command: [conditional
expression](conditional_expression.md) expression](conditional_expression.md)
- if-clause: [conditional branching](if_clause.md) - if-clause: [conditional branching](if_clause.md)
- case statement: [pattern-based branching](case.md) - case statement: [pattern-based branching](case.md)

View File

@ -53,8 +53,8 @@ expansion is to be assigned to an array, another method is possible
using [declaration commands](../../commands/builtin/declare.md): using [declaration commands](../../commands/builtin/declare.md):
`declare -a 'pics=(img{'"$a..$b"'}.png)'; mv "${pics[@]}" ../imgs` This `declare -a 'pics=(img{'"$a..$b"'}.png)'; mv "${pics[@]}" ../imgs` This
is significantly safer, but one must still be careful to control the is significantly safer, but one must still be careful to control the
values of \$a and \$b. Both the exact quoting, and explicitly including values of `$a` and `$b`. Both the exact quoting, and explicitly including
\"-a\" are important. "`-a`" are important.
The brace expansion is present in two basic forms, **string lists** and The brace expansion is present in two basic forms, **string lists** and
**ranges**. **ranges**.
@ -87,24 +87,21 @@ With prefix or suffix strings, the result is a space-separated list of
_I- _want- _my- _money- _back- _I- _want- _my- _money- _back-
The brace expansion is only performed, if the given string list is The brace expansion is only performed, if the given string list is
really a **list of strings**, i.e., if there is a minimum of one \"`,`\" really a **list of strings**, i.e., if there is a minimum of one "`,`"
(comma)! Something like `{money}` doesn't expand to something special, (comma)! Something like `{money}` doesn't expand to something special,
it's really only the text \"`{money}`\". it's really only the text "`{money}`".
## Ranges ## Ranges
{<START>..<END>} {<START>..<END>}
Brace expansion using ranges is written giving the startpoint and the Brace expansion using ranges is written giving the startpoint and the
endpoint of the range. This is a \"sequence expression\". The sequences endpoint of the range. This is a "sequence expression". The sequences
can be of two types can be of two types
- integers (optionally zero padded, optionally with a given increment) - integers (optionally zero padded, optionally with a given increment)
- characters - characters
```{=html}
<!-- -->
```
$ echo {5..12} $ echo {5..12}
5 6 7 8 9 10 11 12 5 6 7 8 9 10 11 12
@ -186,13 +183,10 @@ for.
mkdir /home/bash/test/{foo,bar,baz,cat,dog} mkdir /home/bash/test/{foo,bar,baz,cat,dog}
### Generate numbers with a prefix 001 002 \... ### Generate numbers with a prefix 001 002 ...
- Using a prefix: - Using a prefix:
```{=html}
<!-- -->
```
for i in 0{1..9} 10; do printf "%s\n" "$i";done for i in 0{1..9} 10; do printf "%s\n" "$i";done
If you need to create words with the number embedded, you can use nested If you need to create words with the number embedded, you can use nested
@ -202,9 +196,6 @@ brace:
- Formatting the numbers with printf: - Formatting the numbers with printf:
```{=html}
<!-- -->
```
echo $(printf "img%02d.png " {1..99}) echo $(printf "img%02d.png " {1..99})
See the [text below](#news_in_bash_4.0) for a new Bash 4 method. See the [text below](#news_in_bash_4.0) for a new Bash 4 method.
@ -217,34 +208,33 @@ Can be written as
somecommand -v{,,,,} somecommand -v{,,,,}
\...which is a kind of a hack, but hey, it works. ...which is a kind of a hack, but hey, it works.
<div round info>
#### More fun
The most optimal possible brace expansion to expand n arguments of !!! info "More fun"
course consists of n's prime factors. We can use the \"factor\" program
bundled with GNU coreutils to emit a brace expansion that will expand
any number of arguments.
function braceify { The most optimal possible brace expansion to expand n arguments of
[[ $1 == +([[:digit:]]) ]] || return course consists of n's prime factors. We can use the "factor" program
typeset -a a bundled with GNU coreutils to emit a brace expansion that will expand
read -ra a < <(factor "$1") any number of arguments.
eval "echo $(printf '{$(printf ,%%.s {1..%s})}' "${a[@]:1}")"
}
printf 'eval printf "$arg"%s' "$(braceify 1000000)" function braceify {
[[ $1 == +([[:digit:]]) ]] || return
typeset -a a
read -ra a < <(factor "$1")
eval "echo $(printf '{$(printf ,%%.s {1..%s})}' "${a[@]:1}")"
}
\"Braceify\" generates the expansion code itself. In this example we printf 'eval printf "$arg"%s' "$(braceify 1000000)"
inject that output into a template which displays the most terse brace
expansion code that would expand `"$arg"` 1,000,000 times if evaluated.
In this case, the output is:
eval printf "$arg"{,,}{,,}{,,}{,,}{,,}{,,}{,,,,,}{,,,,,}{,,,,,}{,,,,,}{,,,,,}{,,,,,} "Braceify" generates the expansion code itself. In this example we
inject that output into a template which displays the most terse brace
expansion code that would expand `"$arg"` 1,000,000 times if evaluated.
In this case, the output is:
eval printf "$arg"{,,}{,,}{,,}{,,}{,,}{,,}{,,,,,}{,,,,,}{,,,,,}{,,,,,}{,,,,,}{,,,,,}
</div>
## New in Bash 4.0 ## New in Bash 4.0

View File

@ -33,12 +33,12 @@ In later steps, **if not quoted**, the results undergo [word
splitting](../../syntax/expansion/wordsplit.md) and [pathname splitting](../../syntax/expansion/wordsplit.md) and [pathname
expansion](../../syntax/expansion/globs.md). You have to remember that, because expansion](../../syntax/expansion/globs.md). You have to remember that, because
the word splitting will also remove embedded newlines and other `IFS` the word splitting will also remove embedded newlines and other `IFS`
characters and break the results up into several words. Also you\'ll characters and break the results up into several words. Also you'll
probably get unexpected pathname matches. **If you need the literal probably get unexpected pathname matches. **If you need the literal
results, quote the command substitution!** results, quote the command substitution!**
The second form `` `COMMAND` `` is more or less obsolete for Bash, since The second form `` `COMMAND` `` is more or less obsolete for Bash, since
it has some trouble with nesting (\"inner\" backticks need to be it has some trouble with nesting ("inner" backticks need to be
escaped) and escaping characters. Use `$(COMMAND)`, it's also POSIX! escaped) and escaping characters. Use `$(COMMAND)`, it's also POSIX!
When you [call an explicit subshell](../../syntax/ccmd/grouping_subshell.md) When you [call an explicit subshell](../../syntax/ccmd/grouping_subshell.md)
@ -72,17 +72,17 @@ escaping-neutral, it's nestable, it's also POSIX. But take a look at
the following code snips to decide yourself which form you need under the following code snips to decide yourself which form you need under
specific circumstances: specific circumstances:
**[Nesting]{.underline}** **<u>Nesting</u>**
Backtick form `` `...` `` is not directly nestable. You will have to Backtick form `` `...` `` is not directly nestable. You will have to
escape the \"inner\" backticks. Also, the deeper you go, the more escape escape the "inner" backticks. Also, the deeper you go, the more escape
characters you need. Ugly. characters you need. Ugly.
echo `echo `ls`` # INCORRECT echo `echo `ls`` # INCORRECT
echo `echo \`ls\`` # CORRECT echo `echo \`ls\`` # CORRECT
echo $(echo $(ls)) # CORRECT echo $(echo $(ls)) # CORRECT
**[Parsing]{.underline}** **<u>Parsing</u>**
All is based on the fact that the backquote-form is simple character All is based on the fact that the backquote-form is simple character
substitution, while every `$()`-construct opens an own, subsequent substitution, while every `$()`-construct opens an own, subsequent
@ -91,21 +91,21 @@ normal on a commandline. No special escaping of **nothing** is needed:
echo "$(echo "$(ls)")" # nested double-quotes - no problem echo "$(echo "$(ls)")" # nested double-quotes - no problem
**[Constructs you should avoid]{.underline}** **<u>Constructs you should avoid</u>**
It's not all shiny with `$()`, at least for my current Bash It's not all shiny with `$()`, at least for my current Bash
(`3.1.17(1)-release`. :!: [**Update:** Fixed since `3.2-beta` together (`3.1.17(1)-release`. :!: <u>**Update:** Fixed since `3.2-beta` together
with a misinterpretion of \'))\' being recognized as arithmetic with a misinterpretion of '))' being recognized as arithmetic
expansion \[by redduck666\]]{.underline}). This command seems to expansion by redduck666</u>). This command seems to
incorrectly close the substitution step and echo prints \"ls\" and incorrectly close the substitution step and echo prints "ls" and
\")\": ")":
echo $( echo $(
# some comment ending with a ) # some comment ending with a )
ls ls
) )
It seems that every closing \")\" confuses this construct. Also a (very It seems that every closing ")" confuses this construct. Also a (very
uncommon ;-)) construct like: uncommon ;-)) construct like:
echo $(read VAR; case "$var" in foo) blah ;; esac) # spits out some error, when it sees the ";;" echo $(read VAR; case "$var" in foo) blah ;; esac) # spits out some error, when it sees the ";;"
@ -113,7 +113,7 @@ uncommon ;-)) construct like:
# fixes it: # fixes it:
echo $(read VAR; case "$var" in (foo) blah ;; esac) # will work, but just let it be, please ;-) echo $(read VAR; case "$var" in (foo) blah ;; esac) # will work, but just let it be, please ;-)
**[Conclusion:]{.underline}** **<u>Conclusion:</u>**
In general, the `$()` should be the preferred method: In general, the `$()` should be the preferred method:
@ -141,11 +141,11 @@ target, because command substitution only catches `STDOUT`!
var=$(echo -n $'\n'); echo -n "$var"; # $var == "" var=$(echo -n $'\n'); echo -n "$var"; # $var == ""
var=$(echo -n $'\n'; echo -n x); var="${var%x}"; echo -n "$var" # $var == "\n" var=$(echo -n $'\n'; echo -n x); var="${var%x}"; echo -n "$var" # $var == "\n"
This adds \"x\" to the output, which prevents the trailing newlines of This adds "x" to the output, which prevents the trailing newlines of
the previous commands\' output from being deleted by \$(). the previous commands' output from being deleted by `$()`.
By removing this \"x\" later on, we are left with the previous By removing this "x" later on, we are left with the previous
commands\' output with its trailing newlines. commands' output with its trailing newlines.
## See also ## See also

View File

@ -3,8 +3,8 @@
## General ## General
Unlike on other platforms you may have seen, on UNIX(r), the shell is Unlike on other platforms you may have seen, on UNIX(r), the shell is
responsible for interpreting and expanding globs (\"filename responsible for interpreting and expanding globs ("filename
wildcards\"). A called program will never see the glob itself; it will wildcards"). A called program will never see the glob itself; it will
only see the expanded filenames as its arguments (here, all filenames only see the expanded filenames as its arguments (here, all filenames
matching `*.log`): matching `*.log`):
@ -43,7 +43,7 @@ other `IFS`-characters they contain.
corrections when matching directory names corrections when matching directory names
- when the shell option `globstar` is set, the glob `**` will - when the shell option `globstar` is set, the glob `**` will
recursively match all files and directories. This glob isn't recursively match all files and directories. This glob isn't
\"configurable\", i.e. you **can't** do something like `**.c` to "configurable", i.e. you **can't** do something like `**.c` to
recursively get all `*.c` filenames. recursively get all `*.c` filenames.
- when the shell option `globasciiranges` is set, the bracket-range - when the shell option `globasciiranges` is set, the bracket-range
globs (e.g. `[A-Z]`) use C locale order rather than the configured globs (e.g. `[A-Z]`) use C locale order rather than the configured
@ -56,7 +56,7 @@ other `IFS`-characters they contain.
### nullglob ### nullglob
Normally, when no glob specified matches an existing filename, no Normally, when no glob specified matches an existing filename, no
pathname expansion is performed, and the globs are [**not**]{.underline} pathname expansion is performed, and the globs are <u>**not**</u>
removed: removed:
$ echo "Textfiles here:" *.txt $ echo "Textfiles here:" *.txt
@ -75,7 +75,7 @@ This can be very annoying, for example when you drive a
done done
When no file name matches the glob, the loop will not only output stupid When no file name matches the glob, the loop will not only output stupid
text (\"`BEGIN: *.txt`\"), but also will make the `cat`-command fail text ("`BEGIN: *.txt`"), but also will make the `cat`-command fail
with an error, since no file named `*.txt` exists. with an error, since no file named `*.txt` exists.
Now, when the shell option `nullglob` is set, Bash will remove the Now, when the shell option `nullglob` is set, Bash will remove the
@ -92,11 +92,11 @@ and the glob is gone.
### Glob characters ### Glob characters
- \* - means \'match any number of characters\'. \'/\' is not matched - `*` - means \'match any number of characters\'. \'/\' is not matched
(and depending on your settings, things like \'.\' may or may not be (and depending on your settings, things like \'.\' may or may not be
matched, see above) matched, see above)
- ? - means \'match any single character\' - `?` - means \'match any single character\'
- \[abc\] - match any of the characters listed. This syntax also - `[abc]` - match any of the characters listed. This syntax also
supports ranges, like \[0-9\] supports ranges, like \[0-9\]
For example, to match something beginning with either \'S\' or \'K\' For example, to match something beginning with either \'S\' or \'K\'

View File

@ -28,7 +28,7 @@ The most simple example of this behaviour is a referenced variable:
The `echo` program definitely doesn't care about what a shell variable The `echo` program definitely doesn't care about what a shell variable
is. It is Bash's job to deal with the variable. Bash **expands** the is. It is Bash's job to deal with the variable. Bash **expands** the
string \"`$mystring`\" to \"`Hello world`\", so that `echo` will only string "`$mystring`" to "`Hello world`", so that `echo` will only
see `Hello world`, not the variable or anything else! see `Hello world`, not the variable or anything else!
After all these expansions and substitutions are done, all quotes that After all these expansions and substitutions are done, all quotes that

View File

@ -42,21 +42,22 @@ from a file).
### Scope ### Scope
<note important> Note: According to multiple comments and sources, the !!! note "Note"
scope of process substitution file descriptors is **not** stable, According to multiple comments and sources, the
guaranteed, or specified by bash. Newer versions of bash (5.0+) seem to scope of process substitution file descriptors is **not** stable,
have shorter scope, and substitutions scope seems to be shorter than guaranteed, or specified by bash. Newer versions of bash (5.0+) seem to
function scope. See have shorter scope, and substitutions scope seems to be shorter than
[stackexchange](https://unix.stackexchange.com/questions/425456/conditional-process-substitution) function scope. See
and [stackexchange](https://unix.stackexchange.com/questions/425456/conditional-process-substitution)
[stackoverflow](https://stackoverflow.com/questions/46660020/bash-what-is-the-scope-of-the-process-substitution); and
the latter discussion contains a script that can test the scoping [stackoverflow](https://stackoverflow.com/questions/46660020/bash-what-is-the-scope-of-the-process-substitution);
behavior case-by-case </note> the latter discussion contains a script that can test the scoping
behavior case-by-case
If a process substitution is expanded as an argument to a function, If a process substitution is expanded as an argument to a function,
expanded to an environment variable during calling of a function, or expanded to an environment variable during calling of a function, or
expanded to any assignment within a function, the process substitution expanded to any assignment within a function, the process substitution
will be \"held open\" for use by any command within the function or its will be "held open" for use by any command within the function or its
callees, until the function in which it was set returns. If the same callees, until the function in which it was set returns. If the same
variable is set again within a callee, unless the new variable is local, variable is set again within a callee, unless the new variable is local,
the previous process substitution is closed and will be unavailable to the previous process substitution is closed and will be unavailable to
@ -97,10 +98,11 @@ where those files are written to and destroyed automatically.
### Avoiding subshells ### Avoiding subshells
<WRAP center round info 60%> See Also: !!! info "See Also"
[BashFAQ/024](http://mywiki.wooledge.org/BashFAQ/024) -- *I set See Also:
variables in a loop that's in a pipeline. Why do they disappear after [BashFAQ/024](http://mywiki.wooledge.org/BashFAQ/024) -- *I set
the loop terminates? Or, why can't I pipe data to read?* </WRAP> variables in a loop that's in a pipeline. Why do they disappear after
the loop terminates? Or, why can't I pipe data to read?*
One of the most common uses for process substitutions is to avoid the One of the most common uses for process substitutions is to avoid the
final subshell that results from executing a pipeline. The following is final subshell that results from executing a pipeline. The following is
@ -120,7 +122,7 @@ Due to the pipe, the `while read; do ... done` part is executed in a
subshell (in Bash, by default), which means `counter` is only subshell (in Bash, by default), which means `counter` is only
incremented within the subshell. When the pipeline finishes, the incremented within the subshell. When the pipeline finishes, the
subshell is terminated, and the `counter` visible to `echo` is still at subshell is terminated, and the `counter` visible to `echo` is still at
\"0\"! "0"!
Process substitution helps us avoid the pipe operator (the reason for Process substitution helps us avoid the pipe operator (the reason for
the subshell): the subshell):
@ -149,7 +151,7 @@ note that the space is required in order to disambiguate the syntax from
### Process substitution assigned to a parameter ### Process substitution assigned to a parameter
This example demonstrates how process substitutions can be made to This example demonstrates how process substitutions can be made to
resemble \"passable\" objects. This results in converting the output of resemble "passable" objects. This results in converting the output of
`f`'s argument to uppercase. `f`'s argument to uppercase.
``` bash ``` bash

View File

@ -44,24 +44,25 @@ Tilde expansion is also performed everytime a variable is assigned:
- after **every** `:` (colon) in the assigned value: - after **every** `:` (colon) in the assigned value:
`TARGET=file:~moonman/share` `TARGET=file:~moonman/share`
<note info> As of now (Bash 4.3-alpha) the following constructs !!! info "Note"
**also** works, though it's not a variable assignment: As of now (Bash 4.3-alpha) the following constructs
**also** works, though it's not a variable assignment:
echo foo=~ echo foo=~
echo foo=:~ echo foo=:~
I don't know yet, if this is a bug or intended. </note> I don't know yet, if this is a bug or intended.
This way you can correctly use the tilde expansion in your This way you can correctly use the tilde expansion in your
[PATH](../../syntax/shellvars.md#PATH): [PATH](../../syntax/shellvars.md#PATH):
PATH=~/mybins:~peter/mybins:$PATH PATH=~/mybins:~peter/mybins:$PATH
**Spaces in the referenced pathes?** A construct like\... **Spaces in the referenced pathes?** A construct like...
~/"my directory" ~/"my directory"
\...is perfectly valid and works! ...is perfectly valid and works!
## Home directory ## Home directory
@ -84,7 +85,7 @@ precedence:
- expand to the home directory of the user executing the shell - expand to the home directory of the user executing the shell
(operating system) (operating system)
That means, the variable `HOME` can override the \"real\" home That means, the variable `HOME` can override the "real" home
directory, at least regarding tilde expansion. directory, at least regarding tilde expansion.
## Current working directory ## Current working directory

View File

@ -1,6 +1,7 @@
# Word splitting # Word splitting
FIXME to be continued! !!! warning "FIXME"
to be continued!
Word splitting occurs once any of the following expansions are done (and Word splitting occurs once any of the following expansions are done (and
only then!) only then!)
@ -18,9 +19,9 @@ are **not double-quoted**!
The `IFS` variable holds the characters that Bash sees as word The `IFS` variable holds the characters that Bash sees as word
boundaries in this step. The default contains the characters boundaries in this step. The default contains the characters
- <space> - &lt;space&gt;
- <tab> - &lt;tab&gt;
- <newline> - &lt;newline&gt;
These characters are also assumed when IFS is **unset**. When `IFS` is These characters are also assumed when IFS is **unset**. When `IFS` is
**empty** (nullstring), no word splitting is performed at all. **empty** (nullstring), no word splitting is performed at all.
@ -34,10 +35,10 @@ the expansion result is split at these positions into multiple words.
This doesn't happen when the expansion results were **double-quoted**. This doesn't happen when the expansion results were **double-quoted**.
When a null-string (e.g., something that before expanded to When a null-string (e.g., something that before expanded to
>>nothing<<) is found, it is removed, unless it is quoted (`''` or &gt;&gt;nothing&lt;&lt;) is found, it is removed, unless it is quoted (`''` or
`""`). `""`).
[**Again note:**]{.underline} Without any expansion beforehand, Bash <u>**Again note:**</u> Without any expansion beforehand, Bash
won't perform word splitting! In this case, the initial token parsing won't perform word splitting! In this case, the initial token parsing
is solely responsible. is solely responsible.

View File

@ -10,22 +10,22 @@ tags:
- execution - execution
--- ---
FIXME work in progress\... !!! warning "FIXME"
work in progress...
# Parsing and execution # Parsing and execution
Nearly everything in [Bash grammar](../../syntax/basicgrammar.md) can be broken Nearly everything in [Bash grammar](../../syntax/basicgrammar.md) can be broken
down to a \"simple command\". The only thing Bash has to expand, down to a "simple command". The only thing Bash has to expand,
evaluate and execute is the simple command. evaluate and execute is the simple command.
## Simple command expansion ## Simple command expansion
<div center round info 60%> !!! info "info"
- <http://lists.gnu.org/archive/html/bug-bash/2013-01/msg00040.html> - <http://lists.gnu.org/archive/html/bug-bash/2013-01/msg00040.html>
- <http://lists.research.att.com/pipermail/ast-developers/2013q2/002456.html> - <http://lists.research.att.com/pipermail/ast-developers/2013q2/002456.html>
</div>
This step happens after the initial command line splitting. This step happens after the initial command line splitting.
@ -82,7 +82,7 @@ The behavior regarding the variable assignment errors can be tested:
<div center round info <div center round info
60%><http://lists.gnu.org/archive/html/bug-bash/2013-01/msg00054.html></div> 60%><http://lists.gnu.org/archive/html/bug-bash/2013-01/msg00054.html></div>
**[This one exits the script completely]{.underline}** **<u>This one exits the script completely</u>**
#!/bin/sh #!/bin/sh
# This shell runs in POSIX mode! # This shell runs in POSIX mode!
@ -95,8 +95,8 @@ The behavior regarding the variable assignment errors can be tested:
echo POST echo POST
**[This one terminates only the enclosing compound command (the <u>**This one terminates only the enclosing compound command (the
`{ ...; }`):]{.underline}** `{ ...; }`):**</u>
#!/bin/bash #!/bin/bash
# This shell runs in native Bash-mode! # This shell runs in native Bash-mode!
@ -126,7 +126,8 @@ or install software packages etc. Since this function runs in a separate
execution environment, you can't really influence the main shell with execution environment, you can't really influence the main shell with
it (changing directory, setting variables). it (changing directory, setting variables).
FIXME to be continued !!! warning "FIXME"
to be continued
## See also ## See also

View File

@ -108,7 +108,7 @@ more information on buffering issues.
#### background processes #### background processes
A coprocess\' file descriptors are accessible only to the process from A coprocess' file descriptors are accessible only to the process from
which the `coproc` was started. They are not inherited by subshells. which the `coproc` was started. They are not inherited by subshells.
Here is a not-so-meaningful illustration. Suppose we want to Here is a not-so-meaningful illustration. Suppose we want to
@ -200,7 +200,7 @@ $
#!/bin/bash #!/bin/bash
# we start tee in the background # we start tee in the background
# redirecting its output to the stdout of the script # redirecting its output to the stdout of the script
{ coproc tee { tee logfile ;} >&3 ;} 3>&1 { coproc tee { tee logfile ;} >&3 ;} 3>&1
# we redirect stding and stdout of the script to our coprocess # we redirect stding and stdout of the script to our coprocess
exec >&${tee[1]} 2>&1 exec >&${tee[1]} 2>&1
``` ```
@ -222,7 +222,7 @@ exec >&${tee[1]} 2>&1
### Other shells ### Other shells
ksh93, mksh, zsh, and Bash all support something called \"coprocesses\" ksh93, mksh, zsh, and Bash all support something called "coprocesses"
which all do approximately the same thing. ksh93 and mksh have virtually which all do approximately the same thing. ksh93 and mksh have virtually
identical syntax and semantics for coprocs. A *list* operator: `|&` is identical syntax and semantics for coprocs. A *list* operator: `|&` is
added to the language which runs the preceding *pipeline* as a coprocess added to the language which runs the preceding *pipeline* as a coprocess
@ -258,7 +258,7 @@ more. See
more details more details
The ability to use multiple coprocesses in Bash is considered The ability to use multiple coprocesses in Bash is considered
\"experimental\". Bash will throw an error if you attempt to start more "experimental". Bash will throw an error if you attempt to start more
than one. This may be overridden at compile-time with the than one. This may be overridden at compile-time with the
`MULTIPLE_COPROCS` option. However, at this time there are still issues `MULTIPLE_COPROCS` option. However, at this time there are still issues
-- see the above mailing list discussion. -- see the above mailing list discussion.

View File

@ -26,7 +26,7 @@ A pattern is a **string description**. Bash uses them in various ways:
The pattern description language is relatively easy. Any character The pattern description language is relatively easy. Any character
that's not mentioned below matches itself. The `NUL` character may not that's not mentioned below matches itself. The `NUL` character may not
occur in a pattern. If special characters are quoted, they\'re matched occur in a pattern. If special characters are quoted, they're matched
literally, i.e., without their special meaning. literally, i.e., without their special meaning.
Do **not** confuse patterns with ***regular expressions***, because they Do **not** confuse patterns with ***regular expressions***, because they
@ -34,30 +34,30 @@ share some symbols and do similar matching work.
## Normal pattern language ## Normal pattern language
Sequence Description |Sequence|Description|
---------- ---------------------------------------------------------------------------------------------------------------- |--------|-----------|
`*` Matches **any string**, including the null string (empty string) |`*`|Matches **any string**, including the null string (empty string)|
`?` Matches any **single character** |`?`|Matches any **single character**|
`X` Matches the character `X` which can be any character that has no special meaning |`X`|Matches the character `X` which can be any character that has no special meaning|
`\X` Matches the character `X`, where the character's special meaning is stripped by the backslash |`\X`|Matches the character `X`, where the character's special meaning is stripped by the backslash|
`\\` Matches a backslash |`\\`|Matches a backslash|
`[...]` Defines a pattern **bracket expression** (see below). Matches any of the enclosed characters at this position. |`[...]`|Defines a pattern **bracket expression** (see below). Matches any of the enclosed characters at this position.|
### Bracket expressions ### Bracket expressions
The bracket expression `[...]` mentioned above has some useful The bracket expression `[...]` mentioned above has some useful
applications: applications:
Bracket expression Description |Bracket expression|Description|
---------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |------------------|-----------|
`[XYZ]` The \"normal\" bracket expression, matching either `X`, `Y` or `Z` |`[XYZ]`|The "normal" bracket expression, matching either `X`, `Y` or `Z`|
`[X-Z]` A range expression: Matching all the characters from `X` to `Y` (your current **locale**, defines how the characters are **sorted**!) |`[X-Z]`|A range expression: Matching all the characters from `X` to `Y` (your current **locale**, defines how the characters are **sorted**!)|
`[[:class:]]` Matches all the characters defined by a [POSIX(r) character class](https://pubs.opengroup.org/onlinepubs/009696899/basedefs/xbd_chap07.html#tag_07_03_01): `alnum`, `alpha`, `ascii`, `blank`, `cntrl`, `digit`, `graph`, `lower`, `print`, `punct`, `space`, `upper`, `word` and `xdigit` |`[[:class:]]`|Matches all the characters defined by a [POSIX(r) character class](https://pubs.opengroup.org/onlinepubs/009696899/basedefs/xbd_chap07.html#tag_07_03_01): `alnum`, `alpha`, `ascii`, `blank`, `cntrl`, `digit`, `graph`, `lower`, `print`, `punct`, `space`, `upper`, `word` and `xdigit`|
`[^...]` A negating expression: It matches all the characters that are **not** in the bracket expression |`[^...]`|A negating expression: It matches all the characters that are **not** in the bracket expression|
`[!...]` Equivalent to `[^...]` |`[!...]`|Equivalent to `[^...]`|
`[]...]` or `[-...]` Used to include the characters `]` and `-` into the set, they need to be the first characters after the opening bracket |`[]...]` or `[-...]`|Used to include the characters `]` and `-` into the set, they need to be the first characters after the opening bracket|
`[=C=]` Matches any character that is eqivalent to the collation weight of `C` (current locale!) |`[=C=]`|Matches any character that is eqivalent to the collation weight of `C` (current locale!)|
`[[.SYMBOL.]]` Matches the collating symbol `SYMBOL` |`[[.SYMBOL.]]`|Matches the collating symbol `SYMBOL`|
### Examples ### Examples
@ -66,23 +66,23 @@ Some simple examples using normal pattern matching:
- Pattern `"Hello world"` matches - Pattern `"Hello world"` matches
- `Hello world` - `Hello world`
- Pattern `[Hh]"ello world"` matches - Pattern `[Hh]"ello world"` matches
- => `Hello world` - =&gt; `Hello world`
- => `hello world` - =&gt; `hello world`
- Pattern `Hello*` matches (for example) - Pattern `Hello*` matches (for example)
- => `Hello world` - =&gt; `Hello world`
- => `Helloworld` - =&gt; `Helloworld`
- => `HelloWoRlD` - =&gt; `HelloWoRlD`
- => `Hello` - =&gt; `Hello`
- Pattern `Hello world[[:punct:]]` matches (for example) - Pattern `Hello world[[:punct:]]` matches (for example)
- => `Hello world!` - =&gt; `Hello world!`
- => `Hello world.` - =&gt; `Hello world.`
- => `Hello world+` - =&gt; `Hello world+`
- => `Hello world?` - =&gt; `Hello world?`
- Pattern - Pattern
`[[.backslash.]]Hello[[.vertical-line.]]world[[.exclamation-mark.]]` `[[.backslash.]]Hello[[.vertical-line.]]world[[.exclamation-mark.]]`
matches (using [collation matches (using [collation
symbols](https://pubs.opengroup.org/onlinepubs/009696899/basedefs/xbd_chap07.html#tag_07_03_02_04)) symbols](https://pubs.opengroup.org/onlinepubs/009696899/basedefs/xbd_chap07.html#tag_07_03_02_04))
- => `\Hello|world!` - =&gt; `\Hello|world!`
## Extended pattern language ## Extended pattern language
@ -90,17 +90,17 @@ If you set the [shell option](../internals/shell_options.md) `extglob`, Bash
understands some powerful patterns. A `<PATTERN-LIST>` is one or more understands some powerful patterns. A `<PATTERN-LIST>` is one or more
patterns, separated by the pipe-symbol (`PATTERN|PATTERN`). patterns, separated by the pipe-symbol (`PATTERN|PATTERN`).
--------------------- ------------------------------------------------------------ |Extended pattern|Matches|
`?(<PATTERN-LIST>)` Matches **zero or one** occurrence of the given patterns |----------------|-------|
`*(<PATTERN-LIST>)` Matches **zero or more** occurrences of the given patterns |`?(<PATTERN-LIST>)`|Matches **zero or one** occurrence of the given patterns|
`+(<PATTERN-LIST>)` Matches **one or more** occurrences of the given patterns |`*(<PATTERN-LIST>)`|Matches **zero or more** occurrences of the given patterns|
`@(<PATTERN-LIST>)` Matches **one** of the given patterns |`+(<PATTERN-LIST>)`|Matches **one or more** occurrences of the given patterns|
`!(<PATTERN-LIST>)` Matches anything **except** one of the given patterns |`@(<PATTERN-LIST>)`|Matches **one** of the given patterns|
--------------------- ------------------------------------------------------------ |`!(<PATTERN-LIST>)`|Matches anything **except** one of the given patterns|
### Examples ### Examples
**[Delete all but one specific file]{.underline}** <u>**Delete all but one specific file**</u>
rm -f !(survivior.txt) rm -f !(survivior.txt)
@ -108,15 +108,15 @@ patterns, separated by the pipe-symbol (`PATTERN|PATTERN`).
### Related shell options ### Related shell options
option classification description |option|classification|description|
------------------- ------------------------------------- ------------------------------------------------------------------------------- |------|--------------|-----------|
`dotglob` [globbing](../syntax/expansion/globs.md) see [Pathname expansion customization](../syntax/expansion/globs.md#Customization) |`dotglob`|[globbing](../syntax/expansion/globs.md)|see [Pathname expansion customization](/syntax/expansion/globs.md#Customization)|
`extglob` global enable/disable extended pattern matching language, as described above |`extglob`|global|enable/disable extended pattern matching language, as described above|
`failglob` [globbing](../syntax/expansion/globs.md) see [Pathname expansion customization](../syntax/expansion/globs.md#Customization) |`failglob`|[globbing](../syntax/expansion/globs.md)|see [Pathname expansion customization](/syntax/expansion/globs.md#Customization)|
`nocaseglob` [globbing](../syntax/expansion/globs.md) see [Pathname expansion customization](../syntax/expansion/globs.md#Customization) |`nocaseglob`|[globbing](../syntax/expansion/globs.md)|see [Pathname expansion customization](/syntax/expansion/globs.md#Customization)|
`nocasematch` pattern/string matching perform pattern matching without regarding the case of individual letters |`nocasematch`|pattern/string matching|perform pattern matching without regarding the case of individual letters|
`nullglob` [globbing](../syntax/expansion/globs.md) see [Pathname expansion customization](../syntax/expansion/globs.md#Customization) |`nullglob`|[globbing](../syntax/expansion/globs.md)|see [Pathname expansion customization](/syntax/expansion/globs.md#Customization)|
`globasciiranges` [globbing](../syntax/expansion/globs.md) see [Pathname expansion customization](../syntax/expansion/globs.md#Customization) |`globasciiranges`|[globbing](../syntax/expansion/globs.md)|see [Pathname expansion customization](/syntax/expansion/globs.md#Customization)|
## Bugs and Portability considerations ## Bugs and Portability considerations
@ -152,12 +152,12 @@ to those described above.
\* ksh93 supports arbitrary quantifiers just like ERE using the \* ksh93 supports arbitrary quantifiers just like ERE using the
`{from,to}(pattern-list)` syntax. `{2,4}(foo)bar` matches between 2-4 `{from,to}(pattern-list)` syntax. `{2,4}(foo)bar` matches between 2-4
\"foo\"'s followed by \"bar\". `{2,}(foo)bar` matches 2 or more "foo"'s followed by "bar". `{2,}(foo)bar` matches 2 or more
\"foo\"'s followed by \"bar\". You can probably figure out the rest. So "foo"'s followed by "bar". You can probably figure out the rest. So
far, none of the other shells support this syntax. far, none of the other shells support this syntax.
\* In ksh93, a `pattern-list` may be delimited by either `&` or `|`. `&` \* In ksh93, a `pattern-list` may be delimited by either `&` or `|`. `&`
means \"all patterns must be matched\" instead of \"any pattern\". For means "all patterns must be matched" instead of "any pattern". For
example, `[[ fo0bar == @(fo[0-9]&+([[:alnum:]]))bar ]]` would be true example, `[[ fo0bar == @(fo[0-9]&+([[:alnum:]]))bar ]]` would be true
while `[[ f00bar == @(fo[0-9]&+([[:alnum:]]))bar ]]` is false, because while `[[ f00bar == @(fo[0-9]&+([[:alnum:]]))bar ]]` is false, because
all members of the and-list must be satisfied. No other shell supports all members of the and-list must be satisfied. No other shell supports

View File

@ -46,7 +46,7 @@ applicable description mentions arrays below. Please also see the
[article about arrays](../syntax/arrays.md). [article about arrays](../syntax/arrays.md).
For a more technical view what a parameter is and which types exist, For a more technical view what a parameter is and which types exist,
[see the dictionary entry for \"parameter\"](../dict/parameter.md). [see the dictionary entry for "parameter"](../dict/parameter.md).
## Overview ## Overview
@ -107,16 +107,16 @@ is identical to using `$FOO` like you see it everywhere, but has the
advantage that it can be immediately followed by characters that would advantage that it can be immediately followed by characters that would
be interpreted as part of the parameter name otherwise. Compare these be interpreted as part of the parameter name otherwise. Compare these
two expressions (`WORD="car"` for example), where we want to print a two expressions (`WORD="car"` for example), where we want to print a
word with a trailing \"s\": word with a trailing "s":
echo "The plural of $WORD is most likely $WORDs" echo "The plural of $WORD is most likely $WORDs"
echo "The plural of $WORD is most likely ${WORD}s" echo "The plural of $WORD is most likely ${WORD}s"
[Why does the first one fail?]{.underline} It prints nothing, because a <u>Why does the first one fail?</u> It prints nothing, because a
parameter (variable) named \"`WORDs`\" is undefined and thus printed as parameter (variable) named "`WORDs`" is undefined and thus printed as
\"\" (*nothing*). Without using braces for parameter expansion, Bash "" (*nothing*). Without using braces for parameter expansion, Bash
will interpret the sequence of all valid characters from the introducing will interpret the sequence of all valid characters from the introducing
\"`$`\" up to the last valid character as name of the parameter. When "`$`" up to the last valid character as name of the parameter. When
using braces you just force Bash to **only interpret the name inside using braces you just force Bash to **only interpret the name inside
your braces**. your braces**.
@ -138,9 +138,9 @@ individual indexes or mass arguments. An individual index behaves like a
normal parameter, for the mass expansion, please read the article about normal parameter, for the mass expansion, please read the article about
arrays linked above. arrays linked above.
- \${array\[5\]} - `${array[5]}`
- \${array\[\*\]} - `${array[*]}`
- \${array\[@\]} - `${array[@]}`
## Indirection ## Indirection
@ -158,13 +158,13 @@ you can instead use the form
to enter a level of indirection. The referenced parameter is not to enter a level of indirection. The referenced parameter is not
`PARAMETER` itself, but the parameter whose name is stored as the value `PARAMETER` itself, but the parameter whose name is stored as the value
of `PARAMETER`. If the parameter `PARAMETER` has the value \"`TEMP`\", of `PARAMETER`. If the parameter `PARAMETER` has the value "`TEMP`",
then `${!PARAMETER}` will expand to the value of the parameter named then `${!PARAMETER}` will expand to the value of the parameter named
`TEMP`: `TEMP`:
read -rep 'Which variable do you want to inspect? ' look_var read -rep 'Which variable do you want to inspect? ' look_var
printf 'The value of "%s" is: "%s"\n' "$look_var" "${!look_var}" printf 'The value of "%s" is: "%s"\n' "$look_var" "${!look_var}"
Of course the indirection also works with special variables: Of course the indirection also works with special variables:
@ -193,7 +193,7 @@ of an array, the length of a string, or number of elements in an array
indirectly (see [syntax/arrays#indirection](../syntax/arrays.md#indirection) indirectly (see [syntax/arrays#indirection](../syntax/arrays.md#indirection)
for workarounds). Additionally, the `!`-prefixed parameter expansion for workarounds). Additionally, the `!`-prefixed parameter expansion
conflicts with ksh-like shells which have the more powerful conflicts with ksh-like shells which have the more powerful
\"name-reference\" form of indirection, where the exact same syntax is "name-reference" form of indirection, where the exact same syntax is
used to expand to the name of the variable being referenced. used to expand to the name of the variable being referenced.
Indirect references to [array names](../syntax/arrays.md) are also possible Indirect references to [array names](../syntax/arrays.md) are also possible
@ -235,13 +235,13 @@ of words in the variable while `~~` reverses case for all. Thanks to
</wrap> </wrap>
[**Example: Rename all `*.txt` filenames to lowercase**]{.underline} <u>**Example: Rename all `*.txt` filenames to lowercase**</u>
for file in *.txt; do for file in *.txt; do
mv "$file" "${file,,}" mv "$file" "${file,,}"
done done
[**Note:**]{.underline} Case modification is a handy feature you can <u>**Note:**</u> Case modification is a handy feature you can
apply to a name or a title. Or is it? Case modification was an important apply to a name or a title. Or is it? Case modification was an important
aspect of the Bash 4 release. Bash version 4, RC1 would perform word aspect of the Bash 4 release. Bash version 4, RC1 would perform word
splitting, and then case modification, resulting in title case (where splitting, and then case modification, resulting in title case (where
@ -271,9 +271,6 @@ Assume: `array=(This is some Text)`
- `echo "${array[@]^^}"` - `echo "${array[@]^^}"`
- => `THIS IS SOME TEXT` - => `THIS IS SOME TEXT`
```{=html}
<!-- -->
```
* ''echo "${array[2]^^}"'' * ''echo "${array[2]^^}"''
* => ''SOME'' * => ''SOME''
@ -288,7 +285,7 @@ string `PREFIX`. The elements of the list are separated by the first
character in the `IFS`-variable (<space> by default). character in the `IFS`-variable (<space> by default).
This will show all defined variable names (not values!) beginning with This will show all defined variable names (not values!) beginning with
\"BASH\": "BASH":
$ echo ${!BASH*} $ echo ${!BASH*}
BASH BASH_ARGC BASH_ARGV BASH_COMMAND BASH_LINENO BASH_SOURCE BASH_SUBSHELL BASH_VERSINFO BASH_VERSION BASH BASH_ARGC BASH_ARGV BASH_COMMAND BASH_LINENO BASH_SOURCE BASH_SUBSHELL BASH_VERSINFO BASH_VERSION
@ -319,9 +316,9 @@ Example string (*just a quote from a big man*):
`${PARAMETER#PATTERN}` and `${PARAMETER##PATTERN}` `${PARAMETER#PATTERN}` and `${PARAMETER##PATTERN}`
This form is to remove the described [pattern](../syntax/pattern.md) trying This form is to remove the described [pattern](../syntax/pattern.md) trying
to **match it from the beginning of the string**. The operator \"`#`\" to **match it from the beginning of the string**. The operator "`#`"
will try to remove the shortest text matching the pattern, while will try to remove the shortest text matching the pattern, while
\"`##`\" tries to do it with the longest text matching. Look at the "`##`" tries to do it with the longest text matching. Look at the
following examples to get the idea (matched text ~~marked striked~~, following examples to get the idea (matched text ~~marked striked~~,
remember it will be removed!): remember it will be removed!):
@ -347,7 +344,7 @@ from the end.
### Common use ### Common use
[**How the heck does that help to make my life easier?**]{.underline} <u>**How the heck does that help to make my life easier?**</u>
Well, maybe the most common use for it is to **extract parts of a Well, maybe the most common use for it is to **extract parts of a
filename**. Just look at the following list with examples: filename**. Just look at the following list with examples:
@ -410,7 +407,7 @@ The first one (*one slash*) is to only substitute **the first
occurrence** of the given pattern, the second one (*two slashes*) is to occurrence** of the given pattern, the second one (*two slashes*) is to
substitute **all occurrences** of the pattern. substitute **all occurrences** of the pattern.
First, let's try to say \"happy\" instead of \"conservative\" in our First, let's try to say "happy" instead of "conservative" in our
example string: example string:
${MYSTRING//conservative/happy} ${MYSTRING//conservative/happy}
@ -418,26 +415,26 @@ example string:
=> =>
`Be liberal in what you accept, and conservativehappy in what you send` `Be liberal in what you accept, and conservativehappy in what you send`
Since there is only one \"conservative\" in that example, it really Since there is only one "conservative" in that example, it really
doesn't matter which of the two forms we use. doesn't matter which of the two forms we use.
Let's play with the word \"in\", I don't know if it makes any sense, Let's play with the word "in", I don't know if it makes any sense,
but let's substitute it with \"by\". but let's substitute it with "by".
[**First form: Substitute first occurrence**]{.underline} <u>**First form: Substitute first occurrence**</u>
${MYSTRING/in/by} ${MYSTRING/in/by}
=> `Be liberal inby what you accept, and conservative in what you send` => `Be liberal inby what you accept, and conservative in what you send`
[**Second form: Substitute all occurrences**]{.underline} <u>**Second form: Substitute all occurrences**</u>
${MYSTRING//in/by} ${MYSTRING//in/by}
=> =>
`Be liberal inby what you accept, and conservative inby what you send` `Be liberal inby what you accept, and conservative inby what you send`
[**Anchoring**]{.underline} Additionally you can \"anchor\" an <u>**Anchoring**</u> Additionally you can "anchor" an
expression: A `#` (hashmark) will indicate that your expression is expression: A `#` (hashmark) will indicate that your expression is
matched against the beginning portion of the string, a `%` matched against the beginning portion of the string, a `%`
(percent-sign) will do it for the end portion. (percent-sign) will do it for the end portion.
@ -478,7 +475,7 @@ expanded. Again, a quote from a big man, to have a test text:
MYSTRING="Be liberal in what you accept, and conservative in what you send" MYSTRING="Be liberal in what you accept, and conservative in what you send"
Using echo `${#MYSTRING}`\... Using echo `${#MYSTRING}`...
=> `64` => `64`
@ -493,7 +490,7 @@ There's not much to say about it, mh?
For [arrays](../syntax/arrays.md), this expansion type has two meanings: For [arrays](../syntax/arrays.md), this expansion type has two meanings:
- For **individual** elements, it reports the string length of the - For **individual** elements, it reports the string length of the
element (as for every \"normal\" parameter) element (as for every "normal" parameter)
- For the **mass subscripts** `@` and `*` it reports the number of set - For the **mass subscripts** `@` and `*` it reports the number of set
elements in the array elements in the array
@ -502,11 +499,11 @@ Example:
Assume: `array=(This is a text)` Assume: `array=(This is a text)`
- `echo ${#array[1]}` - `echo ${#array[1]}`
- => 2 (the word \"is\" has a length of 2) - => 2 (the word "is" has a length of 2)
- `echo ${#array[@]}` - `echo ${#array[@]}`
- => 4 (the array contains 4 elements) - => 4 (the array contains 4 elements)
[**Attention:**]{.underline} The number of used elements does not need <u>**Attention:**</u> The number of used elements does not need
to conform to the highest index. Sparse arrays are possible in Bash, to conform to the highest index. Sparse arrays are possible in Bash,
that means you can have 4 elements, but with indexes 1, 7, 20, 31. **You that means you can have 4 elements, but with indexes 1, 7, 20, 31. **You
can't loop through such an array with a counter loop based on the can't loop through such an array with a counter loop based on the
@ -593,7 +590,7 @@ Example:
Assume: `array=(This is a text)` Assume: `array=(This is a text)`
- `echo ${array[0]:2:2}` - `echo ${array[0]:2:2}`
- => `is` (the \"is\" in \"This\", array element 0) - => `is` (the "is" in "This", array element 0)
- `echo ${array[@]:1:2}` - `echo ${array[@]:1:2}`
- => `is a` (from element 1 inclusive, 2 elements are expanded, - => `is a` (from element 1 inclusive, 2 elements are expanded,
i.e. element 1 and 2) i.e. element 1 and 2)
@ -621,7 +618,7 @@ useful, you need to put that parameter syntax in.
read -p "Enter your gender (just press ENTER to not tell us): " GENDER read -p "Enter your gender (just press ENTER to not tell us): " GENDER
echo "Your gender is ${GENDER:-a secret}." echo "Your gender is ${GENDER:-a secret}."
It will print \"Your gender is a secret.\" when you don't enter the It will print "Your gender is a secret." when you don't enter the
gender. Note that the default value is **used on expansion time**, it is gender. Note that the default value is **used on expansion time**, it is
**not assigned to the parameter**. **not assigned to the parameter**.
@ -712,7 +709,7 @@ Let's change our code example from above:
### Assign a default value: Arrays ### Assign a default value: Arrays
For [arrays](../syntax/arrays.md) this expansion type is limited. For an For [arrays](../syntax/arrays.md) this expansion type is limited. For an
individual index, it behaves like for a \"normal\" parameter, the individual index, it behaves like for a "normal" parameter, the
default value is assigned to this one element. The mass-expansion default value is assigned to this one element. The mass-expansion
subscripts `@` and `*` **can not be used here** because it's not subscripts `@` and `*` **can not be used here** because it's not
possible to assign to them! possible to assign to them!
@ -732,7 +729,7 @@ you can specify**:
The above code will simply add a warning if `JAVAPATH` is set (because The above code will simply add a warning if `JAVAPATH` is set (because
it could influence the startup behaviour of that imaginary application). it could influence the startup behaviour of that imaginary application).
Some more unrealistic example\... Ask for some flags (for whatever Some more unrealistic example... Ask for some flags (for whatever
reason), and then, if they were set, print a warning and also print the reason), and then, if they were set, print a warning and also print the
flags: flags:
@ -761,7 +758,7 @@ if variables you need (and that can be empty) are undefined:
### Use an alternate value: Arrays ### Use an alternate value: Arrays
Similar to the cases for [arrays](../syntax/arrays.md) to expand to a default Similar to the cases for [arrays](../syntax/arrays.md) to expand to a default
value, this expansion behaves like for a \"normal\" parameter when using value, this expansion behaves like for a "normal" parameter when using
individual array elements by index, but reacts differently when using individual array elements by index, but reacts differently when using
the mass-expansion subscripts `@` and `*`: the mass-expansion subscripts `@` and `*`:
@ -830,9 +827,6 @@ Removing the first 6 characters from a text string:
<a b cfoo> <a b cfoo> <a> <b> <cfoo> <a b cfoo> <a b cfoo> <a> <b> <cfoo>
` `
```{=html}
<!-- -->
```
- Almost all shells disagree about the treatment of an unquoted `$@`, - Almost all shells disagree about the treatment of an unquoted `$@`,
`${arr[@]}`, `$*`, and `${arr[*]}` when `${arr[@]}`, `$*`, and `${arr[*]}` when
[IFS](http://mywiki.wooledge.org/IFS) is set to null. POSIX is [IFS](http://mywiki.wooledge.org/IFS) is set to null. POSIX is
@ -877,9 +871,6 @@ Removing the first 6 characters from a text string:
pathname expansion and word-splitting to the results, except for pathname expansion and word-splitting to the results, except for
zsh, which doesn't do pathname expansion in its default mode. zsh, which doesn't do pathname expansion in its default mode.
```{=html}
<!-- -->
```
- Additionally, shells disagree about various wordsplitting behaviors, - Additionally, shells disagree about various wordsplitting behaviors,
the behavior of inserting delimiter characters from IFS in `$*`, and the behavior of inserting delimiter characters from IFS in `$*`, and
the way adjacent arguments are concatenated, when IFS is modified in the way adjacent arguments are concatenated, when IFS is modified in
@ -906,35 +897,23 @@ Removing the first 6 characters from a text string:
possible side-effect that can affect expansion halfway through possible side-effect that can affect expansion halfway through
expansion that way. expansion that way.
```{=html}
<!-- -->
```
- As previously mentioned, the Bash form of indirection by prefixing a - As previously mentioned, the Bash form of indirection by prefixing a
parameter expansion with a `!` conflicts with the same syntax used parameter expansion with a `!` conflicts with the same syntax used
by mksh, zsh, and ksh93 for a different purpose. Bash will by mksh, zsh, and ksh93 for a different purpose. Bash will
\"slightly\" modify this expansion in the next version with the "slightly" modify this expansion in the next version with the
addition of namerefs. addition of namerefs.
```{=html}
<!-- -->
```
- Bash (and most other shells) don't allow .'s in identifiers. In - Bash (and most other shells) don't allow .'s in identifiers. In
ksh93, dots in variable names are used to reference methods (i.e. ksh93, dots in variable names are used to reference methods (i.e.
\"Discipline Functions\"), attributes, special shell variables, and "Discipline Functions"), attributes, special shell variables, and
to define the \"real value\" of an instance of a class. to define the "real value" of an instance of a class.
```{=html}
<!-- -->
```
- In ksh93, the `_` parameter has even more uses. It is used in the - In ksh93, the `_` parameter has even more uses. It is used in the
same way as `self` in some object-oriented languages; as a same way as `self` in some object-oriented languages; as a
placeholder for some data local to a class; and also as the placeholder for some data local to a class; and also as the
mechanism for class inheritance. In most other contexts, `_` is mechanism for class inheritance. In most other contexts, `_` is
compatible with Bash. compatible with Bash.
```{=html}
<!-- -->
```
- Bash only evaluates the subscripts of the slice expansion - Bash only evaluates the subscripts of the slice expansion
(`${x:y:z}`) if the parameter is set (for both nested expansions and (`${x:y:z}`) if the parameter is set (for both nested expansions and
arithmetic). For ranges, Bash evaluates as little as possible, i.e., arithmetic). For ranges, Bash evaluates as little as possible, i.e.,
@ -954,13 +933,10 @@ Removing the first 6 characters from a text string:
### Quote Nesting ### Quote Nesting
- In most shells, when dealing with an \"alternate\" parameter - In most shells, when dealing with an "alternate" parameter
expansion that expands to multiple words, and nesting such expansion that expands to multiple words, and nesting such
expansions, not all combinations of nested quoting are possible. expansions, not all combinations of nested quoting are possible.
```{=html}
<!-- -->
```
# Bash # Bash
$ typeset -a a=(meh bleh blerg) b $ typeset -a a=(meh bleh blerg) b
$ IFS=e $ IFS=e
@ -1007,7 +983,7 @@ Consider the following (only slightly far-fetched) code:
"${someCmd[@]-"$someOtherCmd" arg2 "${otherArgs[@]}"}" arg5 "${someCmd[@]-"$someOtherCmd" arg2 "${otherArgs[@]}"}" arg5
This final line is perhaps not the most obvious, but I\'ve run into This final line is perhaps not the most obvious, but I've run into
cases were this type of logic can be desirable and realistic. We can cases were this type of logic can be desirable and realistic. We can
deduce what was intended: deduce what was intended:

View File

@ -27,7 +27,7 @@ All three forms have the very same purpose: **They give you general
control over parsing, expansion and expansion results.** control over parsing, expansion and expansion results.**
Besides these basic variants, there are some special quoting methods Besides these basic variants, there are some special quoting methods
(like interpreting ANSI-C escapes in a string) you\'ll meet below. (like interpreting ANSI-C escapes in a string) you'll meet below.
:!: **ATTENTION** :!: The quote characters (`"`, double quote and `'`, :!: **ATTENTION** :!: The quote characters (`"`, double quote and `'`,
single quote) are a syntax element that influence parsing. It is not single quote) are a syntax element that influence parsing. It is not
@ -77,7 +77,7 @@ beautify your code:
} }
The backslash can be used to mask every character that has a special The backslash can be used to mask every character that has a special
meaning to bash. [Exception:]{.underline} Inside a single-quoted string meaning to bash. <u>Exception:</u> Inside a single-quoted string
(see below). (see below).
## Weak quoting ## Weak quoting
@ -105,7 +105,7 @@ unless you have a file named `*`, spit out an error.
Will work as expected. `$PATH` is expanded, because it's double (weak) Will work as expected. `$PATH` is expanded, because it's double (weak)
quoted. quoted.
If a backslash in double quotes (\"weak quoting\") occurs, there are 2 If a backslash in double quotes ("weak quoting") occurs, there are 2
ways to deal with it ways to deal with it
- if the baskslash is followed by a character that would have a - if the baskslash is followed by a character that would have a
@ -131,7 +131,7 @@ it's surrounded by strong quotes.
In practise that means, to produce a text like `Here's my test...` as a In practise that means, to produce a text like `Here's my test...` as a
single-quoted string, you have to leave and re-enter the single quoting single-quoted string, you have to leave and re-enter the single quoting
to get the character \"`'`\" as literal text: to get the character "`'`" as literal text:
# WRONG # WRONG
echo 'Here's my test...' echo 'Here's my test...'
@ -151,25 +151,25 @@ C-like escape sequences. The Syntax is:
where the following escape sequences are decoded in `string`: where the following escape sequences are decoded in `string`:
Code Meaning |Code|Meaning|
-------------- ------------------------------------------------------------------------------------------------------------------------------------- |----|-------|
`\"` double-quote |`\"`|double-quote|
`\'` single-quote |`\'`|single-quote|
`\\` backslash |`\\`|backslash|
`\a` terminal alert character (bell) |`\a`|terminal alert character (bell)|
`\b` backspace |`\b`|backspace|
`\e` escape (ASCII 033) |`\e`|escape (ASCII 033)|
`\E` escape (ASCII 033) **\\E is non-standard** |`\E`|escape (ASCII 033) **\E is non-standard**|
`\f` form feed |`\f`|form feed|
`\n` newline |`\n`|newline|
`\r` carriage return |`\r`|carriage return|
`\t` horizontal tab |`\t`|horizontal tab|
`\v` vertical tab |`\v`|vertical tab|
`\cx` a control-x character, for example, `$'\cZ'` to print the control sequence composed of Ctrl-Z (`^Z`) |`\cx`|a control-x character, for example, `$'\cZ'` to print the control sequence composed of Ctrl-Z (`^Z`)|
`\uXXXX` Interprets `XXXX` as a hexadecimal number and prints the corresponding character from the character set (4 digits) (Bash 4.2-alpha) |`\uXXXX`|Interprets `XXXX` as a hexadecimal number and prints the corresponding character from the character set (4 digits) (Bash 4.2-alpha)|
`\UXXXXXXXX` Interprets `XXXX` as a hexadecimal number and prints the corresponding character from the character set (8 digits) (Bash 4.2-alpha) |`\UXXXXXXXX`|Interprets `XXXX` as a hexadecimal number and prints the corresponding character from the character set (8 digits) (Bash 4.2-alpha)|
`\nnn` the eight-bit character whose value is the octal value nnn (one to three digits) |`\nnn`|the eight-bit character whose value is the octal value nnn (one to three digits)|
`\xHH` the eight-bit character whose value is the hexadecimal value HH (one or two hex digits) |`\xHH`|the eight-bit character whose value is the hexadecimal value HH (one or two hex digits)|
This is especially useful when you want to pass special characters as This is especially useful when you want to pass special characters as
arguments to some programs, like passing a newline to sed. arguments to some programs, like passing a newline to sed.
@ -181,8 +181,8 @@ The `$'...'` syntax comes from ksh93, but is portable to most modern
shells including pdksh. A shells including pdksh. A
[specification](http://austingroupbugs.net/view.php?id=249#c590) for it [specification](http://austingroupbugs.net/view.php?id=249#c590) for it
was accepted for SUS issue 7. There are still some stragglers, such as was accepted for SUS issue 7. There are still some stragglers, such as
most ash variants including dash, (except busybox built with \"bash most ash variants including dash, (except busybox built with "bash
compatibility\" features). compatibility" features).
## I18N/L10N ## I18N/L10N
@ -197,7 +197,7 @@ quoted string.
If the string was replaced (translated), the result is double quoted. If the string was replaced (translated), the result is double quoted.
In case you\'re a C programmer: The purpose of `$"..."` is the same as In case you're a C programmer: The purpose of `$"..."` is the same as
for `gettext()` or `_()`. for `gettext()` or `_()`.
For useful examples to localize your scripts, please see [Appendix I of For useful examples to localize your scripts, please see [Appendix I of
@ -216,7 +216,7 @@ iterate through. The list can also be in a variable:
mylist="DOG CAT BIRD HORSE" mylist="DOG CAT BIRD HORSE"
**[WRONG]{.underline}** way to iterate through this list: **<u>WRONG</u>** way to iterate through this list:
for animal in "$mylist"; do for animal in "$mylist"; do
echo $animal echo $animal
@ -226,7 +226,7 @@ Why? Due to the double-quotes, technically, the expansion of `$mylist`
is seen as **one word**. The for loop iterates exactly one time, with is seen as **one word**. The for loop iterates exactly one time, with
`animal` set to the whole list. `animal` set to the whole list.
**[RIGHT]{.underline}** way to iterate through this list: **<u>RIGHT</u>** way to iterate through this list:
for animal in $mylist; do for animal in $mylist; do
echo $animal echo $animal
@ -251,7 +251,7 @@ test string with spaces:
mystring="my string" mystring="my string"
And now check that string against the word \"testword\": And now check that string against the word "testword":
[ $mystring = testword ] # WRONG! [ $mystring = testword ] # WRONG!
@ -272,20 +272,16 @@ So what you really want to do is:
Now the command has three parameters, which makes sense for a binary Now the command has three parameters, which makes sense for a binary
(two argument) operator. (two argument) operator.
**[Hint:]{.underline}** Inside the [conditional **<u>Hint:</u>** Inside the [conditional
expression](../syntax/ccmd/conditional_expression.md) (`[[ ]]`) Bash doesn't expression](../syntax/ccmd/conditional_expression.md) (`[[ ]]`) Bash doesn't
perform word splitting, and thus you don't need to quote your variable perform word splitting, and thus you don't need to quote your variable
references - they are always seen as \"one word\". references - they are always seen as "one word".
## See also ## See also
- Internal: [Some words about words\...](../syntax/words.md) - Internal: [Some words about words...](../syntax/words.md)
- Internal: [Word splitting](../syntax/expansion/wordsplit.md) - Internal: [Word splitting](../syntax/expansion/wordsplit.md)
- Internal: [Introduction to expansions and - Internal: [Introduction to expansions and
substitutions](../syntax/expansion/intro.md) substitutions](../syntax/expansion/intro.md)
```{=html}
<!-- -->
```
- External: [Grymore: - External: [Grymore:
Shellquoting](http://www.grymoire.com/Unix/Quote.html) Shellquoting](http://www.grymoire.com/Unix/Quote.html)

View File

@ -1,6 +1,8 @@
# Redirection # Redirection
<wrap left todo>Fix me: To be continued</wrap>\ !!! warning "FIXME"
To be continued
Redirection makes it possible to control where the output of a command Redirection makes it possible to control where the output of a command
goes to, and where the input of a command comes from. It's a mighty goes to, and where the input of a command comes from. It's a mighty
tool that, together with pipelines, makes the shell powerful. The tool that, together with pipelines, makes the shell powerful. The
@ -10,15 +12,18 @@ be executed](../syntax/grammar/parser_exec.md).
Under normal circumstances, there are 3 files open, accessible by the Under normal circumstances, there are 3 files open, accessible by the
file descriptors 0, 1 and 2, all connected to your terminal: file descriptors 0, 1 and 2, all connected to your terminal:
Name FD Description |Name|FD|Description|
---------- ---- -------------------------------------------------------- |----|--|-----------|
`stdin` 0 standard input stream (e.g. keyboard) |`stdin`|0|standard input stream (e.g. keyboard)|
`stdout` 1 standard output stream (e.g. monitor) |`stdout`|1|standard output stream (e.g. monitor)|
`stderr` 2 standard error output stream (usually also on monitor) |`stderr`|2|standard error output stream (usually also on monitor)|
<wrap center info>The terms \"monitor\" and \"keyboard\" refer to the
same device, the **terminal** here. Check your preferred UNIX(r)-FAQ for
details, I\'m too lazy to explain what a terminal is ;-) </wrap> !!! info "INFO"
The terms "monitor" and "keyboard" refer to the
same device, the **terminal** here. Check your preferred UNIX(r)-FAQ for
details, I'm too lazy to explain what a terminal is ;-)
Both, `stdout` and `stderr` are output file descriptors. Their Both, `stdout` and `stderr` are output file descriptors. Their
difference is the **convention** that a program outputs payload on difference is the **convention** that a program outputs payload on
@ -33,7 +38,7 @@ this descriptor, you just use the number:
cat some_file.txt 2>/dev/null cat some_file.txt 2>/dev/null
Whenever you **reference** a descriptor, to point to its current target Whenever you **reference** a descriptor, to point to its current target
file, then you use a \"`&`\" followed by a the descriptor number: file, then you use a "`&`" followed by a the descriptor number:
# this executes the echo-command and redirects its normal output (stdout) to the standard error target # this executes the echo-command and redirects its normal output (stdout) to the standard error target
echo "There was an error" 1>&2 echo "There was an error" 1>&2
@ -45,26 +50,27 @@ these examples are equivalent:
cat >new.txt foo.txt bar.txt cat >new.txt foo.txt bar.txt
>new.txt cat foo.txt bar.txt >new.txt cat foo.txt bar.txt
<wrap center important>Every redirection operator takes one or two !!! info "important"
words as operands. If you have to use operands (e.g. filenames to Every redirection operator takes one or two
redirect to) that contain spaces you **must** quote them!</wrap> words as operands. If you have to use operands (e.g. filenames to
redirect to) that contain spaces you **must** quote them!
## Valid redirection targets and sources ## Valid redirection targets and sources
This syntax is recognized whenever a `TARGET` or a `SOURCE` This syntax is recognized whenever a `TARGET` or a `SOURCE`
specification (like below in the details descriptions) is used. specification (like below in the details descriptions) is used.
Syntax Description |Syntax|Description|
---------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------- |------|-----------|
`FILENAME` references a normal, ordinary filename from the filesystem (which can of course be a FIFO, too. Simply everything you can reference in the filesystem) |`FILENAME`|references a normal, ordinary filename from the filesystem (which can of course be a FIFO, too. Simply everything you can reference in the filesystem)|
`&N` references the current target/source of the filedescriptor `N` (\"duplicates\" the filedescriptor) |`&N`|references the current target/source of the filedescriptor `N` ("duplicates" the filedescriptor)|
`&-` closes the redirected filedescriptor, useful instead of `> /dev/null` constructs (`> &-`) |`&-`|closes the redirected filedescriptor, useful instead of `> /dev/null` constructs (`> &-`)|
`/dev/fd/N` duplicates the filedescriptor `N`, if `N` is a valid integer |`/dev/fd/N`|duplicates the filedescriptor `N`, if `N` is a valid integer|
`/dev/stdin` duplicates filedescriptor 0 (`stdin`) |`/dev/stdin`|duplicates filedescriptor 0 (`stdin`)|
`/dev/stdout` duplicates filedescriptor 1 (`stdout`) |`/dev/stdout`|duplicates filedescriptor 1 (`stdout`)|
`/dev/stderr` duplicates filedescriptor 2 (`stderr`) |`/dev/stderr`|duplicates filedescriptor 2 (`stderr`)|
`/dev/tcp/HOST/PORT` assuming `HOST` is a valid hostname or IP address, and `PORT` is a valid port number or service name: redirect from/to the corresponding TCP socket |`/dev/tcp/HOST/PORT`|assuming `HOST` is a valid hostname or IP address, and `PORT` is a valid port number or service name: redirect from/to the corresponding TCP socket|
`/dev/udp/HOST/PORT` assuming `HOST` is a valid hostname or IP address, and `PORT` is a valid port number or service name: redirect from/to the corresponding UDP socket |`/dev/udp/HOST/PORT`|assuming `HOST` is a valid hostname or IP address, and `PORT` is a valid port number or service name: redirect from/to the corresponding UDP socket|
If a target/source specification fails to open, the whole redirection If a target/source specification fails to open, the whole redirection
operation fails. Avoid referencing file descriptors above 9, since you operation fails. Avoid referencing file descriptors above 9, since you
@ -106,9 +112,10 @@ specified target. It's **equivalent** to
Since Bash4, there's `&>>TARGET`, which is equivalent to Since Bash4, there's `&>>TARGET`, which is equivalent to
`>> TARGET 2>&1`. `>> TARGET 2>&1`.
<wrap center important>This syntax is deprecated and should not be !!! info "important"
used. See the page about [obsolete and deprecated This syntax is deprecated and should not be
syntax](../scripting/obsolete.md).</wrap> used. See the page about [obsolete and deprecated
syntax](../scripting/obsolete.md).
## Appending redirected output and error output ## Appending redirected output and error output
@ -145,7 +152,7 @@ omitted, filedescriptor 0 (`stdin`) is assumed.
TAG TAG
A here-document is an input redirection using source data specified A here-document is an input redirection using source data specified
directly at the command line (or in the script), no \"external\" source. directly at the command line (or in the script), no "external" source.
The redirection-operator `<<` is used together with a tag `TAG` that's The redirection-operator `<<` is used together with a tag `TAG` that's
used to mark the end of input later: used to mark the end of input later:
@ -178,11 +185,12 @@ here-documents.
The tag you use **must** be the only word in the line, to be recognized The tag you use **must** be the only word in the line, to be recognized
as end-of-here-document marker. as end-of-here-document marker.
<wrap center info>It seems that here-documents (tested on versions !!! info "info"
`1.14.7`, `2.05b` and `3.1.17`) are correctly terminated when there is It seems that here-documents (tested on versions
an EOF before the end-of-here-document tag. The reason is unknown, but `1.14.7`, `2.05b` and `3.1.17`) are correctly terminated when there is
it seems to be done on purpose. Bash 4 introduced a warning message when an EOF before the end-of-here-document tag. The reason is unknown, but
end-of-file is seen before the tag is reached.</wrap> it seems to be done on purpose. Bash 4 introduced a warning message when
end-of-file is seen before the tag is reached.
## Here strings ## Here strings
@ -201,7 +209,7 @@ The here-string will append a newline (`\n`) to the data.
## Multiple redirections ## Multiple redirections
More redirection operations can occur in a line of course. The order is More redirection operations can occur in a line of course. The order is
**important**! They\'re evaluated from **left to right**. If you want to **important**! They're evaluated from **left to right**. If you want to
redirect both, `stderr` and `stdout` to the same file (like `/dev/null`, redirect both, `stderr` and `stdout` to the same file (like `/dev/null`,
to hide it), this is **the wrong way**: to hide it), this is **the wrong way**:
@ -216,12 +224,12 @@ Why? Relatively easy:
- initially, `stdout` points to your terminal (you read it) - initially, `stdout` points to your terminal (you read it)
- same applies to `stderr`, it's connected to your terminal - same applies to `stderr`, it's connected to your terminal
- `2>&1` redirects `stderr` away from the terminal to the target for - `2>&1` redirects `stderr` away from the terminal to the target for
`stdout`: **the terminal** (again\...) `stdout`: **the terminal** (again...)
- `1>/dev/null` redirects `stdout` away from your terminal to the file - `1>/dev/null` redirects `stdout` away from your terminal to the file
`/dev/null` `/dev/null`
What remains? `stdout` goes to `/dev/null`, `stderr` still (or better: What remains? `stdout` goes to `/dev/null`, `stderr` still (or better:
\"again\") goes to the terminal. You have to swap the order to make it "again") goes to the terminal. You have to swap the order to make it
do what you want: do what you want:
``` bash ``` bash

File diff suppressed because it is too large Load Diff

View File

@ -10,12 +10,13 @@ tags:
- recognition - recognition
--- ---
# Words\... # Words...
FIXME This article needs a review, it covers two topics (command line !!! warning "FIXME"
splitting and word splitting) and mixes both a bit too much. But in This article needs a review, it covers two topics (command line
general, it's still usable to help understand this behaviour, it's splitting and word splitting) and mixes both a bit too much. But in
\"wrong but not wrong\". general, it's still usable to help understand this behaviour, it's
"wrong but not wrong".
One fundamental principle of Bash is to recognize words entered at the One fundamental principle of Bash is to recognize words entered at the
command prompt, or under other circumstances like variable-expansion. command prompt, or under other circumstances like variable-expansion.
@ -32,7 +33,7 @@ by a space. When you enter an echo command at the Bash prompt, Bash will
look for those special characters, and use them to separate the look for those special characters, and use them to separate the
parameters. parameters.
You don't know what I\'m talking about? I\'m talking about this: You don't know what I'm talking about? I'm talking about this:
$ echo Hello little world $ echo Hello little world
Hello little world Hello little world
@ -48,9 +49,9 @@ blank characters is treated as a single blank.** Here's an example:
Bash splits the command line at the blanks into words, then it calls Bash splits the command line at the blanks into words, then it calls
echo with **each word as an argument**. In this example, echo is called echo with **each word as an argument**. In this example, echo is called
with three arguments: \"`Hello`\", \"`little`\" and \"`world`\"! with three arguments: "`Hello`", "`little`" and "`world`"!
[Does that mean we can't echo more than one Space?]{.underline} Of <u>Does that mean we can't echo more than one Space?</u> Of
course not! Bash treats blanks as special characters, but there are two course not! Bash treats blanks as special characters, but there are two
ways to tell Bash not to treat them special: **Escaping** and ways to tell Bash not to treat them special: **Escaping** and
**quoting**. **quoting**.
@ -63,9 +64,9 @@ Escaping is done by preceeding the character with a backslash:
Hello little world Hello little world
None of the escaped spaces will be used to perform word splitting. Thus, None of the escaped spaces will be used to perform word splitting. Thus,
echo is called with one argument: \"`Hello little world`\". echo is called with one argument: "`Hello little world`".
Bash has a mechanism to \"escape\" an entire string: **Quoting**. In the Bash has a mechanism to "escape" an entire string: **Quoting**. In the
context of command-splitting, which this section is about, it doesn't context of command-splitting, which this section is about, it doesn't
matter which kind of quoting you use: weak quoting or strong quoting, matter which kind of quoting you use: weak quoting or strong quoting,
both cause Bash to not treat spaces as special characters: both cause Bash to not treat spaces as special characters:
@ -76,7 +77,7 @@ both cause Bash to not treat spaces as special characters:
$ echo 'Hello little world' $ echo 'Hello little world'
Hello little world Hello little world
[What is it all about now?]{.underline} Well, for example imagine a <u>What is it all about now?</u> Well, for example imagine a
program that expects a filename as an argument, like cat. Filenames can program that expects a filename as an argument, like cat. Filenames can
have spaces in them: have spaces in them:
@ -141,41 +142,37 @@ and the first review is:
echo The file is named $MYFILE echo The file is named $MYFILE
The parser will scan for blanks and mark the relevant words (\"splitting The parser will scan for blanks and mark the relevant words ("splitting
the command line\"): the command line"):
Initial command line splitting: | Initial command line splitting: | | | | | |
--------------------------------- -------- -------- -------- --------- ----------- |---------------------------------|--------|--------|--------|---------|-----------|
Word 1 Word 2 Word 3 Word 4 Word 5 Word 6 | Word 1 | Word 2 | Word 3 | Word 4 | Word 5 | Word 6 |
`echo` `The` `file` `is` `named` `$MYFILE` | `echo` | `The` | `file` | `is` | `named` | `$MYFILE` |
A [parameter/variable expansion](../syntax/pe.md) is part of that command A [parameter/variable expansion](../syntax/pe.md) is part of that command
line, Bash will perform the substitution, and the [word line, Bash will perform the substitution, and the [word
splitting](../syntax/expansion/wordsplit.md) on the results: splitting](../syntax/expansion/wordsplit.md) on the results:
Word splitting after substitution: | Word splitting after substitution: | | | | | | |
------------------------------------ -------- -------- -------- --------- -------- ------------ |------------------------------------|--------|--------|--------|---------|--------|------------|
Word 1 Word 2 Word 3 Word 4 Word 5 Word 6 Word 7 | Word 1 | Word 2 | Word 3 | Word 4 | Word 5 | Word 6 | Word 7 |
`echo` `The` `file` `is` `named` `THE` `FILE.TXT` | `echo` | `The` | `file` | `is` | `named` | `THE` | `FILE.TXT` |
Now let's imagine we quoted `$MYFILE`, the command line now looks like: Now let's imagine we quoted `$MYFILE`, the command line now looks like:
echo The file is named "$MYFILE" echo The file is named "$MYFILE"
Word splitting after substitution (quoted!): | Word splitting after substitution (quoted!): | | | | | |
---------------------------------------------- -------- -------- -------- --------- ---------------- |----------------------------------------------|--------|--------|--------|---------|----------------|
Word 1 Word 2 Word 3 Word 4 Word 5 Word 6 | Word 1 | Word 2 | Word 3 | Word 4 | Word 5 | Word 6 |
`echo` `The` `file` `is` `named` `THE FILE.TXT` | `echo` | `The` | `file` | `is` | `named` | `THE FILE.TXT` |
***Bold Text*72i love this world**===== See also ===== # See also
- Internal: [Quoting and character escaping](../syntax/quoting.md) - Internal: [Quoting and character escaping](../syntax/quoting.md)
- Internal: [Word splitting](../syntax/expansion/wordsplit.md) - Internal: [Word splitting](../syntax/expansion/wordsplit.md)
- Internal: [Introduction to expansions and - Internal: [Introduction to expansions and
substitutions](../syntax/expansion/intro.md) substitutions](../syntax/expansion/intro.md)
```{=html}
<!-- -->
```
- External: [Grymore: - External: [Grymore:
Shellquoting](http://www.grymoire.com/Unix/Quote.html) Shellquoting](http://www.grymoire.com/Unix/Quote.html)